一、上节回顾:
1、网络=物理连接介质+互联网协议
2、OSI七层:应、表、会、传(tcp/udp),网(IP),数(ethernet),物
3、Tep三次握手建立连接,四次挥手断开连接
connet()————>accept()
4、ip+port:标识全世界范围内独一无二的一个应用程序
server.bind((ip,port))
5、C/S
Client:ip+port会随意变
Server:
一定要绑定ip+port
应该支持并发连接
服务端一旦开启一直运行到世界末日
二、今日内容:
坑:reve(1024)
粘包问题:自定义应用层协议
TCP:流式协议
1、 操作命令:
(1)dir 查看当前文件夹下有哪些子文件夹
(2)tasklist 查看运行的哪些程序:
(3)管道符: tasklist : findstr pychar
(4) ipconfig 查看IP配置
2、subprosess 模块
import subprocess obj=subprocess.Popen("dir",shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) print(obj.stdout.read().decode("gbk")) print(obj.stderr.read().decode("gbk"))
解析:管道的内容只能取一次(服务端)
3、粘包现象: TCP的nagle 算法
只有TCP 才会出现粘包现象(TCP协议是流式协议)
粘包:把数据量较小并且时间间隔比较短的包合成一个包发送
“linux:网卡最大 参数单元:1500个字节 (千兆网卡)
以太网 是物理层上面的 也是*网卡“
万兆网卡 是光纤模块 (最大参数单元)
如果超出字节分片发送(以太网协议 的标准)
4、struct模块
import struct # 帮我们把数字转成固定长度的bytes类型 res=struct.pack("i",12323) print(res,len(res)) #将bytes 类型转为数字 res1=struct.unpack("i",res) print(res1[0])
5、json模块:
import json header_dic={ 'md5':'asdfasdfasdfasdfasdfasdf', 'total_size':11111111111111111111, 'filename':'a.txt' } header_json=json.dumps(header_dic) header_bytes=header_json.encode('utf-8') print(len(header_bytes)) header_size=struct.pack('i',len(header_bytes)) print(header_size)
6、流程:
完整版:
7、解决粘包问题:
import subprocess import struct import json from socket import * server=socket(AF_INET,SOCK_STREAM) server.bind(('127.0.0.1',8090)) # print(server) server.listen(5) while True: conn,addr=server.accept() # print(conn) print(addr) while True: try: cmd=conn.recv(8096) if not cmd:break #针对linux #执行命令 cmd=cmd.decode('utf-8') #调用模块,执行命令,并且收集命令的执行结果,而不是打印 obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) stdout=obj.stdout.read() stderr=obj.stderr.read() # 1:先制作报头,报头里放:数据大小, md5, 文件 header_dic = { 'total_size':len(stdout)+len(stderr), 'md5': 'xxxxxxxxxxxxxxxxxxx', 'filename': 'xxxxx', 'xxxxx':'123123' } header_json = json.dumps(header_dic) header_bytes = header_json.encode('utf-8') header_size = struct.pack('i', len(header_bytes)) # 2: 先发报头的长度 conn.send(header_size) # 3:先发报头 conn.send(header_bytes) # 4:再发送真实数据 conn.send(stdout) conn.send(stderr) except ConnectionResetError: break conn.close() server.close()
import struct import json from socket import * client=socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',8089)) while True: cmd=input('>>: ').strip() if not cmd:continue client.send(cmd.encode('utf-8')) # 1:先收报头长度 obj = client.recv(4) header_size = struct.unpack('i', obj)[0] # 2:先收报头,解出报头内容 header_bytes = client.recv(header_size) header_json = header_bytes.decode('utf-8') header_dic = json.loads(header_json) print(header_dic) total_size = header_dic['total_size'] # 3:循环收完整数据 recv_size=0 res=b'' while recv_size < total_size: recv_data=client.recv(1024) res+=recv_data recv_size+=len(recv_data) print(res.decode('gbk')) client.close()