今日内容大纲
- 解决粘包法案高大上版
- 基于UDP协议的socket
- socketserver
1. 解决粘包方案高大上版
-
服务端
import socket import subprocess import struct import json server = socket.socket() server.bind(('127.0.0.1', 8848)) server.listen(5) while 1: conn, addr = server.accept() # 阻塞, 等待客户机连接 while 1: try: from_client_cmd = conn.recv(1024) if from_client_cmd.upper() == b'Q': break obj = suprocess.Popen(from_client_cmd.decode('utf-8'), shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE, ) result = (obj.stdout.read() + obj.stderr.reak()).decode('gbk').encode('utf-8') print(f'文件的总字节个数{len(result)}') # int 类型 #制作头部字典 head_dic = { 'file_name':'文件名', 'md5':'a54g78a787ga6gdahr68t78fd7h6s7', 'file_size':len(result) } # 将head_dic转化成字符串 head_dic_json = json.dumps(head_dic) # 将head_dic_json转化成bytes类型 head_dic_json_bytes = head_dic_json.encode('utf-8') # 获得head_dic_json_bytes总字节个数 head_dic_json_bytes_len = len(head_dic_json_bytes) # 将head_dic_json_bytes_len转化成固定长度bytes类型 four_bytes = struct.pack('i', head_dic_json_bytes_len) # 固定4个字节(struct作用) conn.send(four_bytes) conn.send(head_dic_json_bytes) conn.send(result) except ConnectionResetError: break # 关闭通道 conn.close() server.close()
-
客户端
import socket import struct import json client = socket.socket() client.connect(('127.0.0.1', 8848)) # 链接服务端 while 1: to_server_data = input('命令>>>') client.send(to_server_data.encode('utf-8')) if to_server_data.upper() == 'Q': break # 获取固定头部 four_bytes = client.recv(4) head_dic_json_bytes_len = struct.unpack('i', four_bytes)[0] # 接收head_dic_json_bytes数据 head_dic_json_bytes = client.recv(head_dic_json_bytes_len) # 解码成json head_dic_json = head_dic_json_bytes.decode('utf-8') # 解码成head_dic head_dic = json.loads(head_dic_json) total = b'' while len(total) < head_dic['file_size']: total += client.recv(1024) print(f'结果:{total.decode("utf-8")}') client.close()
2. 基于UDP协议的socket
-
服务端
import socket # 基于网络的UDP的socket对象 server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server.bind(('127.0.0.1', 9000)) while 1: msg, addr = server.recvfrom(1024) print(f'来自{addr}客户的消息:{msg.decode("utf-8")}') to_client_data = input('>>') server.sendto(to_cliend_data.encode('utf-8'), addr) server.close
-
客户端
import socket client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) while 1: to_server_data = input('>>>') client.sendto(to_server_data.encode('utf-8'), ('127.0.0.1', 9000)) from_server_data, addr = client.ercvfrom(1024) print(f'来自服务端{addr}的消息:{from_server_data.decode("utf-8")}')
3.socketserver
-
代码
import socketserver class MyServer(socketserver.BaseRequestHandler): # 类名随便定义,但是必须继承socketserver.BaseRequestHandler此类 def handle(self): # 必须以此命名 while 1: # self.request == conn 管道对象 from_client_data = self.request.recv(1024) print(f'客户端的数据:{from_client_data.decode("utf-8")}') to_client_data = input('》》》') self.request.send(to_client_data.encode('utf-8')) if __name__ == '__main__': ip_port = ('127.0.0.1', 8848) server = socketserver.ThreadingTCPServer(ip_port, MyServer) # 对 socketserver.ThreadingTCPServer 类实例化对象,将ip地址,端口号以及自己定义的类名传入,并返回一个对象 server.serve_forever() # 开启服务端 import socket import time client = socket.socket() # 创建客户端对象 client.connect(('127.0.0.1', 8848)) # 链接服务端 while 1: to_server_data = input('请输入:>>>>') client.send(('玮哥说:' + to_server_data).encode('utf-8')) if to_server_data.upper() == 'Q': break from_server_data = client.recv(1024) # 阻塞 print(f"服务端回复:{from_server_data.decode('utf-8')}") client.close()
找下面类中的int类型
先研究BaseServer类中的init
研究server_bind方法