客户端
import socket client = socket.socket() # 以默认的TCP协议建立双向通道 client.connect((‘127.0.0.1‘, 8080)) # 服务端的ip 和 port client.send(b‘hello‘) # 向服务端发送信息,二进制格式 data = client.recv(1024) # 接收服务端传来的信息 print(data) client.close() # 关闭服务端
服务端
import socket server = socket.socket() # 实例化socket对象,不传参数默认TCP协议 server.bind((‘127.0.0.1‘, 8080)) # bind((host, prot)) 绑定端口和协议 server.listen() # conn, addr = server.accept() # 等待接听信息, conn:双向传输通道 addr:客户端地址 data = conn.recv(1024) # 将客户端传输过来的内容赋值给data 接受1024个字节数据 print(data) conn.send(b‘hello word‘) # 向客户端传输内容,只能是二进制格式 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(1027) print(data)
服务端
import socket ‘‘‘ 服务端有固定的ip和port,要24小时不间断服务客户端 ‘‘‘ server = socket.socket() # 生成一个对象 server.bind((‘127.0.0.1‘, 8080)) # 绑定ip和port server.listen(5) # 半连接池 while True: # 连接循环 conn, addr = server.accept() # 当一个客户端断开通道后,等待下一个客户端的连接 while True: # 通信循环 try: data = conn.recv(1024) print(data) # mac与linux 客户端异常退出后,服务端并不会报错,会循环打印 b‘‘ if len(data) == 0:break # 用户兼容mac与linux conn.send(data.upper()) # 将数据大写发送给客户端 except ConnectionAbortedError: # 捕捉 客户端异常退出 的错误信息 break # 当客户端异常退出后结束通信循环 conn.close() # 当客户端异常退出后关闭通道,进入下一次连接循环
‘‘‘ struct模块的作用是将数据长度转换成固定长度的内容 ‘‘‘ import struct res = ‘asdfghjkl‘ print(‘装包前长度‘, len(res)) # >>> 装包前长度 9 # 装包 成固定长度为4 res1 = struct.pack(‘i‘, len(res)) print(‘装包后长度‘, len(res1)) # >>> 装包后长度 4 # 解包 res2 = struct.unpack(‘i‘, res1)[0] print(‘解包后长度‘, res2) # 解包后长度 9 d = { ‘name‘:‘waller‘, ‘file_size‘: 33335555555444444446666666, ‘s‘:1 } print(len(d)) # 字典键值对个数 import json d_size = json.dumps(d) print(len(d_size)) # 字典转字符转后的字符个数 # 装包 报头 成固定长度为4 msg1 = struct.pack(‘i‘, len(d_size)) print(msg1) # >>> b‘C\x00\x00\x00‘ print(len(msg1)) # 解包 报头 获得原长度 msg2 = struct.unpack(‘i‘, msg1)[0] print(msg2)
服务端
1.先制作一个发送给客户端的字典
2.制作字典的报头
3.发送字典的报头
4.发送字典
5.再发真实数据
客户端
1.先接受字典的报头
2.解析拿到字典的数据长度
3.接受字典
4.从字典中获取真实数据的长度
5.接受真实数据
服务端
import socket import subprocess import struct import json server = socket.socket() server.bind((‘127.0.0.1‘,8080)) server.listen(5) while True: conn, addr = server.accept() while True: try: cmd = conn.recv(1024) if len(cmd) == 0:break cmd = cmd.decode(‘utf-8‘) obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) res = obj.stdout.read() + obj.stderr.read() print(res) # res 是二进制格式 d = {‘name‘:‘jason‘,‘file_size‘:len(res),‘info‘:‘asdhjkshasdad‘} json_d = json.dumps(d) # 将字典序列化成字符串,便于编码传输 # 1.先制作一个字典的报头 header = struct.pack(‘i‘,len(json_d)) # 报头自动被编码成二进制 print(header) # >>> b‘<\x00\x00\x00‘ # 2.发送字典报头 conn.send(header) # 3.发送字典 conn.send(json_d.encode(‘utf-8‘)) # 将字典编码发送 # 4.再发真实数据 conn.send(res) # conn.send(obj.stdout.read()) # conn.send(obj.stderr.read()) except ConnectionResetError as e: print(e) break conn.close()
客户端
import socket import struct import json 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) # 1.先接受字典报头 header_dict = client.recv(4) # 接收的报头是二进制格式 # 2.解析报头 获取字典的长度 dict_size = struct.unpack(‘i‘,header_dict)[0] # 解包的时候一定要加上索引0 print(dict_size) # 3.接收字典数据 dict_bytes = client.recv(dict_size) # 按照字典的长度接收字典 dict_json = json.loads(dict_bytes.decode(‘utf-8‘)) # 将字典反序列化并解码出来 print(dict_json) # 4.从字典中获取信息 recv_size = 0 real_data = b‘‘ # 初始化二进制 while recv_size < dict_json.get(‘file_size‘): # dict_json.get(‘file_size‘) = len(res) data = client.recv(1024) # 接收1024个字节 real_data += data # 每读取一次二进制数据拼接一次 recv_size += len(data) # 每次读取的长度相加,当总长度和len(res)向同时,结束 print(real_data.decode(‘gbk‘)) # 将读取的二进制数据解码出来
原文:https://www.cnblogs.com/waller/p/11318306.html