Python Day31:socket套接字、TCP协议及其经常使用内置函数、及服务端与客户端标准代码

## socket

```python
socket 就是套接字:
CP用主机的IP地址加上主机上的端口号做为TCP链接的端点,这种端点就叫作套接字
它是网络通讯过程当中端点的抽象表示,包含进行网络通讯必需的五种信息:链接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
#网络通讯和链接,主要有3个参数:通讯的目的IP地址、使用的传输层协议(TCP或UDP)和使用的端口号。Socket原意是 “插座”。经过将这3个参数结合起来,与一个“插座”Socket绑定,应用层就能够和传输层经过套接字接口,区分来自不一样应用程序进程或网络链接的通讯,实现数据传输的并发服务
就是一个封装好的模块,要学习的就是模块的使用方法 
socket分为两种类型  
​    AF_UNIX : 进程间通信
​    AF_INET : 网络通信  
需明确:关于网络协议 和socket相关概念,对于全部编程语言都是一致的,区别仅仅是各编程语言的函数名称不一样
要明确一点:不管是客户端服务器端都使用的都是socket对象
 
```

## socket内经常使用函数

```python
服务端套接字函数
s.bind()    绑定(主机,端口号)到套接字
s.listen()  开始TCP监听
s.accept()  被动接受TCP客户的链接,(阻塞式)等待链接的到来

客户端套接字函数
s.connect()     主动初始化TCP服务器链接
s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数
s.recv()            接收TCP数据
s.send()            发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall()         发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom()        接收UDP数据
s.sendto()          发送UDP数据
s.getpeername()     链接到当前套接字的远端的地址
s.getsockname()     当前套接字的地址
s.getsockopt()      返回指定套接字的参数
s.setsockopt()      设置指定套接字的参数
s.close()           关闭套接字

面向锁的套接字方法
s.setblocking()     设置套接字的阻塞与非阻塞模式
s.settimeout()      设置阻塞套接字操做的超时时间
s.gettimeout()      获得阻塞套接字操做的超时时间

```

<p style="color:red">注意TCP中必须先启动服务器再启动客户端,不然客户端因为没法连接服务器,直接报错!</p>

## TCP服务端

```python
import socket
ip_port=('127.0.0.1',8081)#电话卡
BUFSIZE=1024
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
s.bind(ip_port) #手机插卡
s.listen(5)     #手机待机

while True:                         #新增接收连接循环,能够不停的接电话
    conn,addr=s.accept()            #手机接电话
    # print(conn)
    # print(addr)
    print('接到来自%s的电话' %addr[0])
    while True:                         #新增通讯循环,能够不断的通讯,收发消息
        msg=conn.recv(BUFSIZE)             #听消息,听话
        print(msg,type(msg))
        conn.send(msg.upper())          #发消息,说话
    conn.close()                    #挂电话
s.close()                       #手机关机


```

## TCP客户端

```python
import socket
ip_port=('127.0.0.1',8081)
BUFSIZE=1024
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect_ex(ip_port)           #拨电话

while True:                             #新增通讯循环,客户端能够不断发收消息
    msg=input('>>: ').strip()
    if len(msg) == 0:continue
    s.send(msg.encode('utf-8'))         #发消息,说话(只能发送字节类型)
    
    feedback=s.recv(BUFSIZE)                           #收消息,听话
    print(feedback.decode('utf-8'))
s.close()                                       #挂电话

```

当客服端与服务器连接成功后,若是一方没有执行close,而是直接强行终止程序(或是遇到异常被迫终止),都会致使另外一方发送问题

linux下,不会抛出异常会致使接收数据的一方,recv方法不断的收到空消息,形成死循环

要使应用程序可以在不一样平台正常工做,那须要分别处理这两个问题

解决方案以下:

```python
import socket
ip_port=('127.0.0.1',8081)
BUFSIZE=1024
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(ip_port)
s.listen(5)    
while True:                        
    conn,addr=s.accept()           
    while True:                         
        try:
            msg=conn.recv(BUFSIZE)             
            #linux不会抛出异常,会接收到空消息,这里加以判断
            if not msg:
                conn.close()
                break
            print(msg,type(msg))
            conn.send(msg.upper())        
       except ConnectionResetError:
            #只要异常发生则意味着对方以及关闭了,服务器也相应的关闭该连接
            conn.close()
            break
    conn.close()              
s.close()                       

```

至此TCP通信模板程序就完成了,能够不断的接收新的连接,不断的收发消息,而且不会由于客户端强制关闭而异常退出!
相关文章
相关标签/搜索