2018-7-22-Python全栈开发day30-socket原理与粘包-part3-基于TCP实现远程命令,并且解决粘包现象
1.知识准备
subprocess模块
运行一个命令,将这个命令的结果,放到管道内,然后从管道内取出,
res=subprocee.Popen('dir',shell=True,stdout=subprocess.PIPE)#将命令输出的结果放到管道内
res.stdout.read()#读取管道内的数据,且只能读取一次,是b形式的
2.
服务端:
from socket import * import subprocess ip_port=('127.0.0.1',8080) back_log=5 buffer_size=1024 tcp_server=socket(AF_INET,SOCK_STREAM) tcp_server.bind(ip_port) tcp_server.listen(back_log) while 1:#循环监听, con,addr=tcp_server.accept() print('this is new client ',addr) while 1: data=con.recv(buffer_size) if not data:continue res=subprocess.Popen(data.decode('gbk'),shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)#拿到的是b形式的 if not res: print('执行成功') err_msg=res.stderr.read()#b形式 if err_msg: con.send(err_msg) else: out_msg=res.stdout.read() con.send(out_msg)
客户端“
from socket import * client_server=socket(AF_INET,SOCK_STREAM) client_server.connect(('127.0.0.1',8080)) while True: msg=input('please input cmd') if not msg:continue client_server.send(msg.encode('gbk')) data=client_server.recv(1024) print('this is recv',data.decode('gbk'))
3.问题:粘包
3.1粘包的原因:
对于tcp来说,,粘包有两个原因,
1.数据较小,间隔较短,多段数据在一块,另一端在接收的时候只收到一条#tcp中send和recv是不对应的
2.数据较大,一次性并不能从内核态缓存中全部拿出来,下一次再拿的时候先拿上一次遗留的
3.2 粘包的解决思路
在每次send之前,将需要发的数据长度告知接收方,然后接收方改变buffer_size,来确定一次性可以取完。
3.3 程序实现
服务端:
# from socket import * # import subprocess # ip_port=('127.0.0.1',8080) # back_log=5 # buffer_size=1024 # # tcp_server=socket(AF_INET,SOCK_STREAM) # tcp_server.bind(ip_port) # tcp_server.listen(back_log) # # while 1:#循环监听, # con,addr=tcp_server.accept() # print('this is new client ',addr) # while 1: # data=con.recv(buffer_size) # if not data:continue # res=subprocess.Popen(data.decode('gbk'),shell=True, # stdout=subprocess.PIPE, # stdin=subprocess.PIPE, # stderr=subprocess.PIPE)#拿到的是b形式的 # if not res: # print('执行成功') # err_msg=res.stderr.read()#b形式 # if err_msg: # con.send(err_msg) # else: # out_msg=res.stdout.read() # con.send(out_msg) #解决粘包 from socket import * import subprocess ip_port=('127.0.0.1',8080) back_log=5 buffer_size=1024 tcp_server=socket(AF_INET,SOCK_STREAM) tcp_server.bind(ip_port) tcp_server.listen(back_log) while 1:#循环监听, con,addr=tcp_server.accept() print('this is new client ',addr) while 1: data=con.recv(buffer_size) if not data:continue res=subprocess.Popen(data.decode('gbk'),shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)#拿到的是b形式的 if not res: print('执行成功') err_msg=res.stderr.read()#b形式 if err_msg: res1=err_msg else: res1=res.stdout.read() #以上实现原理相同,对数据进行处理 # length=len(res1) con.send(str(length).encode('gbk')) data2=con.recv(1024) if data2.decode('utf-8') == 'ready': con.send(res1)
客户端:
# from socket import * # client_server=socket(AF_INET,SOCK_STREAM) # client_server.connect(('127.0.0.1',8080)) # # while True: # msg=input('please input cmd') # if not msg:continue # client_server.send(msg.encode('gbk')) # data=client_server.recv(1024) # print('this is recv',data.decode('gbk')) # from socket import * client_server=socket(AF_INET,SOCK_STREAM) client_server.connect(('127.0.0.1',8080)) buffer_size=1024 while True: msg=input('please input cmd') if not msg:continue client_server.send(msg.encode('gbk')) data_length=client_server.recv(buffer_size)#就是收到的数据长度 data_length1=int(data_length.decode('gbk'))#进行解码并转换为整形 if data_length1 <= buffer_size: client_server.send('ready'.encode('gbk')) else: buffer_size=data_length1 client_server.send('ready'.encode('gbk')) data2 = client_server.recv(buffer_size) print('this is recv',data2.decode('gbk'))
                    
                
                
            
        
浙公网安备 33010602011771号