一粘包

  TCP协议是面向对象的,面向流的,提高可靠性服务。使用了优化算法,Nagle算法。将多次间隔较少且数据量小的数据,合并成一个大的数据块,然后进行封包。这样接收端就很难分辨出来。TCP协议数据是可靠的,但是会粘包。

  问题的关键是另一端并不知道你要传多少字节的数据,处理办法是必须先传一个报头,告诉另一端我要发送多少,然后另一端就接收指定数量的字节,这是可以做到的。粘包问题就解决了。

  借助struct模块来解决。

二 struct模块

import struct
res=struct.pack('i',111)
print(res,len(res))
res=struct.pack('i',11111111)
print(res,len(res))

  输出:

b'o\x00\x00\x00' 4
b'\xc7\x8a\xa9\x00' 4

  struct模块对int类型的数字进行字节化,(bytes方法是把字符串类型的字节化),一定范围内的数字字节化后的长度都是4个字节。

import struct
res=struct.pack('i',111) #'i’是表示整数格式
print(res,len(res))
ret=struct.unpack('i',res) #unpack的结果是一个元组
print(ret)
print(ret[0]) #取第一个值,便是pack的整数

  输出:

b'o\x00\x00\x00' 4
(111,)
111

三 彻底解决粘包问题。

  思路:

  A想要给B发送一个字典,这个字典包含filename,filesize,md5等等信息,怎么发送呢

  先用json把字典序列化为字符串,然后字节化。用len方法取其长度 length。这个length就是字典字符串化字节化的长度。

  在用sturct模块,pack方法将上面取到的length,字节化的结果,传给B,这个结果固定长度为4。

  B这边,先recv(4),拿到后,用struct的unpack方法,取到的就是字典字符串化字节化的长度length。

  在recv(length),拿到的就是字典字符串化字节化的结果。这个结果怎么来的就怎么倒回去,decode,json.loads(),拿到字典。拿到filesize。

  while循环,接收长度为filesize的字节。

  到此,粘包问题解决,大功告成。

  

  简言之:

    服务器  1 发送报头的长度。借用struct模块                          客户端     1 接收报头的长度。   recv(4),struct模块unpack取到报头的长度length

         2 发送报头。借用json模块                                                      2 接收报头。              recv(lenth)。json反序列化得到报头。报头中有‘’size‘’

           3 发送真实数据                                                                       3 接收真实数据           报头中含有size,对应真实数据的数据。

            

  客户端:

import socket
import struct
import json
#1、买手机
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #2、打电话
phone.connect(('127.0.0.1',8092)) #3、发收消息
while True:
cmd=input('>>: ').strip()
if cmd == 'quit':break
if not cmd:continue
phone.send(cmd.encode('utf-8'))
#先收报头长度
obj=phone.recv(4)
header_size=struct.unpack('i',obj)[0] #再收报头
header_bytes=phone.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']
filename=header_dic['filename'] total_data=b''
recv_size=0
with open(filename,'wb') as f:
while recv_size < total_size:
recv_data=phone.recv(1024)
total_data+=recv_data
recv_size+=len(recv_data)
print(total_data.decode('gbk')) #4、挂电话
phone.close()

 服务端

import socket
import subprocess
import struct
import json
#1、买手机
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #2、绑定手机卡
# phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(('192.168.11.53',8080)) #3、开机
phone.listen(5) #4、等电话连接
print('starting...')
while True: #连接循环
conn,addr=phone.accept()
print('IP:%s,PORT:%s' %(addr[0],addr[1])) #5、收发消息
while True: #通信循环
try:
cmd=conn.recv(1024) #最大收1024
if not cmd:break #针对linux #执行命令
obj=subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout=obj.stdout.read()
stderr=obj.stderr.read()
#制作报头
header_dic = {'filename': 'a.txt',
'total_size': len(stdout)+len(stderr),
'md5': 'asdfa123xvc123'} header_json = json.dumps(header_dic) header_bytes = header_json.encode('utf-8') #先发报头的长度。发送的长度是字典格式的报头经过json化的bytes化处理的长度。经过struct.pack,固定长度为4个字节。
conn.send(struct.pack('i',len(header_bytes)))
#再发送报头。发送的报头是json化,bytes化后的报头。
conn.send(header_bytes)
#最后发送真实数据
conn.send(stdout)
conn.send(stderr)
except Exception:
break #6、挂电话
conn.close() #7、关机
phone.close()

python 粘包问题及解决方法的更多相关文章

  1. 网络编程——TCP协议、UDP协议、socket套接字、粘包问题以及解决方法

    网络编程--TCP协议.UDP协议.socket套接字.粘包问题以及解决方法 TCP协议(流式协议) ​ 当应用程序想通过TCP协议实现远程通信时,彼此之间必须先建立双向通信通道,基于该双向通道实现数 ...

  2. python粘包分析与解决

    TCP与UDP协议 TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务.收发两端(客户端和服务器端)都要有一一成对的socket,因此 ...

  3. 网络编程 TCP协议:三次握手,四次回收,反馈机制 socket套接字通信 粘包问题与解决方法

    TCP协议:传输协议,基于端口工作 三次握手,四次挥手 TCP协议建立双向通道. 三次握手, 建连接: 1:客户端向服务端发送建立连接的请求 2:服务端返回收到请求的信息给客户端,并且发送往客户端建立 ...

  4. TCP协议的粘包现象和解决方法

    # 粘包现象 # serverimport socket sk = socket.socket()sk.bind(('127.0.0.1', 8005))sk.listen() conn, addr ...

  5. 网络编程----粘包以及粘包问题的解决、FTP上传

    一.粘包现象 让我们基于tcp先制作一个远程执行命令的程序(1:执行错误命令 2:执行ls 3:执行ifconfig) 注意注意: res=subprocess.Popen(cmd.decode('u ...

  6. 什么是TCP粘包?怎么解决这个问题

    在socket网络编程中,都是端到端通信,由客户端端口+服务端端口+客户端IP+服务端IP+传输协议组成的五元组可以明确的标识一条连接.在TCP的socket编程中,发送端和接收端都有成对的socke ...

  7. 在国内使用maven下载jar包非常慢的解决方法

    在国内使用maven下载jar包非常慢的解决方法 1.原因: 很多jar包在国外环境,所以会很慢. 2.解决方法 maven支持镜像环境下载,所以首先找到maven的conf目录中的settings. ...

  8. Python更新pip出现错误解决方法

    Python更新pip出现错误解决方法 更新pip python -m pip install --upgrade pip 查看时报错 解决方法 在命令栏(即win+r)输入:easy_install ...

  9. python cmd 窗口 中文乱码 解决方法 (附:打印不同颜色)

    python cmd 窗口 中文乱码 解决方法 (附:打印不同颜色) 前言 在 python 开发中,有时候想通过cmd窗口来和用户交互,比如显示信息之类的,会比自己创建 GUI 来的方便,但是随之而 ...

随机推荐

  1. 爬虫遇到HTTP Error 403的问题

    # coding=gbk from bs4 import BeautifulSoup import requests import urllib x = 1 y = 1 def crawl(url): ...

  2. js中异步方案比较完整版(callback,promise,generator,async)

    JS 异步已经告一段落了,这里来一波小总结 1. 回调函数(callback) setTimeout(() => { // callback 函数体 }, 1000) 缺点:回调地狱,不能用 t ...

  3. SVN:The working copy is locked due to a previous error (一)

    使用 Cornerstone  时,碰到如题问题,SVN无法Update.Commit等操作. 解决办法:Working Copies ⟹ '右键' ⟹ Clean 即可解决! 尊重作者劳动成果,转载 ...

  4. new和delete的动态分配。

    c++对象模型 视频的实际操作  note: 1.虚函数有虚指针,所以是4,不管有几个虚函数, 都只有一个vptr来存放调用的虚函数的地址. 2.子类的内存是父类内存的加自己的数据内存. 3.clas ...

  5. Codevs1033 蚯蚓的游戏

    题目描述 Description 在一块梯形田地上,一群蚯蚓在做收集食物游戏.蚯蚓们把梯形田地上的食物堆积整理如下: a(1,1)  a(1,2)…a(1,m) a(2,1)  a(2,2)  a(2 ...

  6. centos7重启后/etc/resolv.conf 被还原解决办法

    每次重启服务器后,/etc/resolv.conf文件就被自动还原了,最后发现是被Network Manager修改了. 查看Network Manager服务状态 systemctl status ...

  7. Python学习笔记:输入输出,注释,运算符,变量,数字类型,序列,条件和循环控制,函数,迭代器与生成器,异常处理

    输入输出 输入函数input()和raw_input() 在Python3.x中只有input()作为输入函数,会将输入内容自动转换str类型: 在Python2.x中有input()和raw_inp ...

  8. Java常用api和操作必背

    1.数组排序 Java的Arrays类(java.util中)包含用来操作数组(比如排序和搜索)的各种方法. Arrays.sort(各种类型数组) 2.数组转字符串 1)打印数组时可用Arrays. ...

  9. 流式处理框架storm浅析(上篇)

    本文来自网易云社区 作者:汪建伟 前言 前一段时间参与哨兵流式监控功能设计,调研了两个可以做流式计算的框架:storm和spark streaming,我负责storm的调研工作.断断续续花了一周的时 ...

  10. 用asp.net+Jquery+Ajax+sqlserver编写的 (英语六级记单词)

    开始(英语对程序员的重要性引用) 出处 英语的重要性已经毋庸置疑,对于程序员来说更甚,一些最新的技术资料是英文的,如果想进入外企英语也是一个很重要的条件.对于程序员来说怎样学习好英语,在此谈一下我的一 ...