14.socket - TCP粘包
2018-09-05 本文已影响22人
芝麻酱的简书
粘包产生的原因:
1.因为TCP优化算法,如果客户端一次发送数据过小,会导致多次数据合并成一个大包一起发送给服务端
2.如果客户端发送数据过大,会导致数据拆分成多个包,分多次发送给服务端
粘包解决:
服务端:
#low版解决粘包版本
# 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 True:
# conn,addr=tcp_server.accept()
# print('新的客户端链接',addr)
# while True:
# #收
# try:
# cmd=conn.recv(buffer_size)
# if not cmd:break
# print('收到客户端的命令',cmd)
#
# #执行命令,得到命令的运行结果cmd_res
# res=subprocess.Popen(cmd.decode('utf-8'),shell=True,
# stderr=subprocess.PIPE,
# stdout=subprocess.PIPE,
# stdin=subprocess.PIPE)
# err=res.stderr.read()
# if err:
# cmd_res=err
# else:
# cmd_res=res.stdout.read()
#
# #发
# if not cmd_res:
# cmd_res='执行成功'.encode('gbk')
#
# length=len(cmd_res)
# conn.send(str(length).encode('utf-8'))
# client_ready=conn.recv(buffer_size)
# if client_ready == b'ready':
# conn.send(cmd_res)
# except Exception as e:
# print(e)
# break
from socket import *
import subprocess
import struct
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 True:
conn,addr=tcp_server.accept()
print('新的客户端链接',addr)
while True:
#收
try:
cmd=conn.recv(buffer_size)
if not cmd:break
print('收到客户端的命令',cmd)
#执行命令,得到命令的运行结果cmd_res
res=subprocess.Popen(cmd.decode('utf-8'),shell=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE)
err=res.stderr.read()
if err:
cmd_res=err
else:
cmd_res=res.stdout.read()
#发
if not cmd_res:
cmd_res='执行成功'.encode('gbk')
length=len(cmd_res)
data_length=struct.pack('i',length)
conn.send(data_length)
conn.send(cmd_res)
except Exception as e:
print(e)
break
客户端解决:
#low版解决粘包版
# from socket import *
# ip_port=('127.0.0.1',8080)
# back_log=5
# buffer_size=1024
#
# tcp_client=socket(AF_INET,SOCK_STREAM)
# tcp_client.connect(ip_port)
#
# while True:
# cmd=input('>>: ').strip()
# if not cmd:continue
# if cmd == 'quit':break
#
# tcp_client.send(cmd.encode('utf-8'))
#
#
# #解决粘包
# length=tcp_client.recv(buffer_size)
# tcp_client.send(b'ready')
#
# length=int(length.decode('utf-8'))
#
# recv_size=0
# recv_msg=b''
# while recv_size < length:
# recv_msg += tcp_client.recv(buffer_size)
# recv_size=len(recv_msg) #1024
#
#
# print('命令的执行结果是 ',recv_msg.decode('gbk'))
# tcp_client.close()
from socket import *
import struct
from functools import partial
ip_port=('127.0.0.1',8080)
back_log=5
buffer_size=1024
tcp_client=socket(AF_INET,SOCK_STREAM)
tcp_client.connect(ip_port)
while True:
cmd=input('>>: ').strip()
if not cmd:continue
if cmd == 'quit':break
tcp_client.send(cmd.encode('utf-8'))
#解决粘包
length_data=tcp_client.recv(4)
length=struct.unpack('i',length_data)[0]
recv_msg=''.join(iter(partial(tcp_client.recv, buffer_size), b''))
print('命令的执行结果是 ',recv_msg.decode('gbk'))
tcp_client.close()