scoket模块
简单版本原理解析:
服务端的设置:
客户端的设置:
注意:
127.0.0.1为本机回还地址(只能自己识别自己,其他人无法访问!)
send 和 recv要相对应,不能出现两边同时接收或发送的情况!
recv 接收的数据是来自内存的,至于是谁发送到内存的无需考虑。
TCP特点:
会将数据量小的并且时间间隔短的数据一次性打包发送给对方。
解决黏包问题:
客户端:
1.先接受字典的报头
2.解析拿到字典的数据长度
3.接受字典
4.从字典中获取真实数据的长度
5.接受真实数据
struct 模块:
用于固定发送数据的长度。
res = struct.pack('i',len(一个值))
stuct.unpack('i',res)[0]
1 客户端设置: 2 import socket 3 import struct 4 import json 5 client = socket.socket() 6 client.connect(('127.0.0.1',8080)) 7 while True: 8 msg = input('请输入指令:').encode('utf-8') 9 client.send(msg) 10 if len(msg) == 0:continue 11 header = client.recv(4) 12 dict_size = struct.unpack('i',header)[0] 13 dict = client.recv(dict_size) 14 dict_json = json.loads(dict.decode('utf-8')) 15 print(dict_json) 16 recv_size = 0 17 real_data = b'' 18 while recv_size < dict_json.get('file_size'): 19 data = client.recv(1024) 20 real_data += data 21 recv_size += len(data) 22 print(real_data.decode('gbk')) 23 服务端设置: 24 import socket 25 import subprocess 26 import json 27 import struct 28 server = socket.socket() 29 server.bind(('127.0.0.1',8080)) 30 server.listen(5) 31 32 while True: 33 conn, addr = server.accept() 34 while True: 35 try: 36 cmd = conn.recv(1024) 37 if len(cmd) == 0:break 38 cmd = cmd.decode('utf-8') 39 obj = subprocess.Popen( 40 cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) 41 res = obj.stdout.read()+obj.stderr.read() 42 d = {'name':'yyj', 'file_size':len(res)} 43 json_d = json.dumps(d) 44 header = struct.pack('i',len(json_d)) 45 conn.send(header) 46 conn.send(json_d.encode('utf-8')) 47 conn.send(res) 48 except ConnectionResetError as e: 49 print(e) 50 break 51 conn.close()
连接循环和通信循环的设计:
1 #服务端: 2 import socket 3 4 """ 5 服务端 6 固定的ip和port 7 24小时不间断提供服务 8 """ 9 server = socket.socket() # 生成一个对象 10 server.bind(('127.0.0.1',8080)) # 绑定ip和port 11 server.listen(5) # 半连接池 12 13 while True: 14 conn, addr = server.accept() # 等到别人来 conn就类似于是双向通道 15 print(addr) # ('127.0.0.1', 51323) 客户端的地址 16 while True: 17 try: 18 data = conn.recv(1024) 19 print(data) # b'' 针对mac与linux 客户端异常退出之后 服务端不会报错 只会一直收b'' 20 if len(data) == 0:break 21 conn.send(data.upper()) 22 except ConnectionResetError as e: 23 print(e) 24 break 25 conn.close() 26 27 客户端: 28 import socket 29 30 31 client = socket.socket() 32 client.connect(('127.0.0.1',8080)) 33 34 while True: 35 msg = input('>>>:').encode('utf-8') 36 if len(msg) == 0:continue 37 client.send(msg) 38 data = client.recv(1024) 39 print(data)
用于处理服务端重新启动时端口没有及时释放问题: