一、socket初识
①服务端
import socket server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) # 半连接池 conn, addr = server.accept() # 待机等待接听电话 data = conn.recv(1024) # 接听别人说话,只接收1024字节 print(data) conn.send(b'hello girl') # 跟别人说话 conn.close() # 关闭通信连接 server.close() # 关闭服务端
②客户端
import socket client = socket.socket() client.connect(('127.0.0.1', 8080)) client.send(b'hello how much?') data = client.recv(1024) print(data) client.close()
二、通信循环
①服务端
服务端: 有固定的ip和port 24小时不间断提供服务 import socket server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) conn, addr = server.accept() while True: try: data = conn.recv(1024) if len(data) == 0:break print(data) conn.send(data.upper()) except ConnectionResetError: break conn.close() server.close()
②客户端
import socket client = socket.socket() client.connect(('127.0.0.1', 8080)) while True: msg = input('>>>:').encode('utf-8') if len(msg) == 0: continue client.send(msg) data = client.recv(1024) print(data)
三、链接循环
①服务端
import socket server = socket.socket() server.bind(('127.0.0.1', 8080)) server.listen(5) while True: conn, addr = server.accept() while True: try: data = conn.recv(1024) if len(data) == 0:break print(data) conn.send(data.upper()) except ConnectionResetError: break conn.close() server.close()
②客户端
import socket client = socket.socket() client.connect(('127.0.0.1', 8080)) while True: msg = input('>>>:').encode('utf-8') if len(msg) == 0: continue client.send(msg) data = client.recv(1024) print(data)
四、粘包问题的产生
1、粘包问题
接收方:我不知道我要接收的数据的总长度
发送方:由于tcp协议的内部优化算法 会将数据量比较小的并且时间间隔比较短的数据一次性打包发送
2、如何解决
①发送数据直接先告诉对方数据量的大小
②利用struct模块定制我们自己的消息传输协议
3、最终版本解决粘包问题
客户端:
①制作字典报头
②发送报头
③再发送字典
④再发你的真实数据
服务端:
①先收4个长度的报头
②解析报头,获取字典长度
③接收字典(反序列化) ——>> 获取字典里面所有信息
④接收真实数据
五、TCP协议特点:会将数据量比较小的并且时间间隔比较短的数据一次性打包发送
①服务端
import socket server = socket.socket() server.bind(('127.0.0.1',8088)) server.listen(5) # 半连接池 conn,addr = server.accept() data = conn.recv(5) # 指定收到数据量的大小为5个,如果不指定,还是1024,就会出现粘包现象 print(data) # b'hello' data = conn.recv(5) print(data) # b'hello' data = conn.recv(4) print(data) # b'hell'
②客户端
import socket client = socket.socket() client.connect(('127.0.0.1',8088)) client.send(b'hello') client.send(b'hello') client.send(b'hello')
六、struct模块
import struct data = 'dfsafsagdsfgfafsdafsdafafryuio' # 服务端 res = struct.pack('i', len(data)) # 打包:把一个数据打包为长度固定为4 print(len(res)) # 4 print(res) # b'x1ex00x00x00' # 客户端 ret = struct.unpack('i', res)[0] # 解包:数据真实长度 print(ret) # 30