1.先说下subprocess模块的用法,为了举个黏包的例子
# 通过一个例子 来认识网络编程中的一个重要的概念 # 所有的客户端执行server端下发的指令,执行完毕后,客户端将执行结果给返回给服务端 import subprocess # 这个模块其实并不好用,这里为了举例子。调用操作系统的命令模块 res = subprocess.Popen('dir', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 执行dir命令,并将标准输出和错误内容装到了管道中 print('stdout : ', res.stdout.read().decode('gbk')) # 从管道中获取控制台的内容,windows控制台执行完毕后,得到的是bytes类型的,需要解码成gbk才可不乱码显示,windows控制台返回的是gbk的,所以这里要gbk解码 print('stderror: ', res.stderr.read().decode('gbk'))
2.写一个tcp的server端和client,模拟黏包的现象,tcp端发送windows的命令给client,client接收后执行该命令后,将控制台返回的内容传输到server端
tcpserver.py
# 通过一个例子 来认识网络编程中的一个重要的概念 # 所有的客户端执行server端下发的指令,执行完毕后,客户端将执行结果给返回给服务端 # 基于tcp实现远程执行命令 # 在server下发windows操作系统命令给client,client执行完毕后返回给sercer # 出现了黏包现象 # 数据乱了,数据没有接收完,下次接收接收到了未接收到的数据等现象 # tcp不会丢包,会黏包。 # 当传输的包很大的时候,tcp协议会将其拆分开进行传输。 import socket sk = socket.socket() sk.bind(('127.0.0.1', 8080)) sk.listen() conn, addr = sk.accept() while True: cmd = input('输入想要客户端windows系统想要执行的命令:') conn.send(cmd.encode('utf-8')) msg = conn.recv(1024).decode('utf-8') print(msg) conn.close() sk.close()
tcpclient.py
# client接收服务端命令 import socket import subprocess sk = socket.socket() sk.connect(('127.0.0.1', 8080)) while True: cmd = sk.recv(1024).decode('utf-8') res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = 'stdout : ' + res.stdout.read().decode('gbk') stderr = 'stderr : ' + res.stderr.read().decode('gbk') #print(stdout) #print(stderr) # res.stdout.read() 为cmd命令执行后返回的结果,返回的是bytes类型数据 sk.send(stdout.encode('utf-8')) sk.send(stderr.encode('utf-8')) sk.close()
3.udp不黏包,但会丢包例子,与上类似
udpserver.py
# 测试结果,udp不会黏包,但udp会丢包,数据发送出去后,一旦另一端接收的缓存不够大,而发送的数据很大时,未接收的数据,会丢弃掉。同时udp大了缓存限制会丢弃包 import socket sk = socket.socket(type=socket.SOCK_DGRAM) #sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) # 避免服务重启的时候报address already in use。加上这个解决 sk.bind(('127.0.0.1', 8081)) msg, addr = sk.recvfrom(1024) while True: cmd = input('输入想要客户端windows系统想要执行的命令:') if cmd == 'q': break sk.sendto(cmd.encode('utf-8'), addr) msg, addr = sk.recvfrom(1024) print(msg.decode('utf-8')) sk.close()
udpclient.py
# client接收服务端命令 import socket import subprocess sk = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1', 8081) sk.sendto(b'hello', ip_port) while True: cmd, addr= sk.recvfrom(1024) res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = 'stdout : ' + res.stdout.read().decode('gbk') stderr = 'stderr : ' + res.stderr.read().decode('gbk') #print(stdout) #print(stderr) # res.stdout.read() 为cmd命令执行后返回的结果,返回的是bytes类型数据 sk.sendto(stdout.encode('utf-8'), ip_port) sk.sendto(stderr.encode('utf-8'), ip_port) sk.close()
4.tcp为什么会黏包
黏包是这样出现的
tcp的拆包机制是类似这样的
5.udp为什么不会黏包