CSIC_716_20191203【 socket网络编程,以及沾包问题的高级解决方式】
- AF_UNIX(本机通信)
- AF_INET(TCP/IP – IPv4)
- AF_INET6(TCP/IP – IPv6)
- SOCK_STREAM(TCP流)
- SOCK_DGRAM(UDP数据报)
远程操作服务端的命令行。
解决沾包问题的方法: 以远程连接服务端的命令行为例子。
server服务端
# _*_ coding: gbk _*_ # @Author: Wonder import socket import json import subprocess import struct # 将数字类型变成固定长度, from socket import SOL_SOCKET, SO_REUSEADDR sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sk.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 重用地址 sk.bind(('127.0.0.1', 9900)) # 绑定地址和端口号 ,这里ip和端口组成一个元组 sk.listen(5) # 启动监听,允许最大连接数量为3 while True: sock, addr = sk.accept() # 三次握手建立的管道,支持多个客户端client进行连接 while True: try: bin_cmd = sock.recv(1024) # 二进制, 接收二进制的cmd cmd = bin_cmd.decode('utf-8') # 转成真是的cmd sub_obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 操作本机cmd stdout = sub_obj.stdout.read() # 系统生成的二进制,windows环境下是gbk编码格式,Linux下是utf-8格式。 stderr = sub_obj.stderr.read() ''' 高级版本在于改造报头 ''' head_content = { 'filename': 'kazami.txt', 'secreatkey': 123456, 'header': len(stdout) + len(stderr) } head_text = json.dumps(head_content).encode('utf-8') # 序列化之后进行编码 sock.send(struct.pack('i', len(head_text))) # 发报头长度 sock.send(head_text) # 发报头 sock.send(stdout) sock.send(stderr) # sock.send(str2.encode('utf-8')) except ConnectionResetError: # 当判断client断开连接后,跳出循环 break sock.close() sk.close()
client 客户端
# _*_ coding: gbk _*_ # @Author: Wonder import socket import struct import json sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 和 Internet中的通信,流格式。 sk.connect(('127.0.0.1', 9900)) # 连接到服务端的绑定地址 while True: cmd = input('>>>').strip() if not cmd: continue sk.send(cmd.encode('utf-8')) # 必须要发送二进制的数据。 res1 = sk.recv(4) #取报头长度 text_text_len = struct.unpack('i', res1)[0] # 获取报头的真实长度 bin_head_text = sk.recv(text_text_len) # 读取报头内容 head_text =json.loads(bin_head_text.decode('utf-8')) print(head_text) data_size = head_text.get('header') # 真实内容长度 res_byt = b'' real_size = 0 while real_size < data_size: #当真实拼接的长度小于数据长度时,不断拼接,直到完整数据拼出来。 res = sk.recv(4444) # 最大为缓存,过大没有意义。 res_byt += res real_size += len(res) print(res_byt.decode('gbk')) print(real_size) sk.close()