博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自定义报头解决粘包问题
阅读量:4698 次
发布时间:2019-06-09

本文共 2613 字,大约阅读时间需要 8 分钟。

什么是黏包问题:

  首先黏包问题只会在基于TCP协议的socket编程中出现,出现的原因是:由于TCP是字节流协议,客户端在接受服务短发来的数据时,会把数据组织成数据流接收。若客户端的socket对象调用的recv(size)方法中的size值大于或小于服务端发送的数据的长度,都会使多个数据包合成一个包传送,造成数据的混乱,从而形成黏包。

  解决方法是:自定义报头。中心思想是:服务端定制报头(对发送数据的描述信息),服务端在发送真正的数据之前,先向客户端发送报头,客户端接受到报头之后,先读取报头的内容,让客户端知道数据的长度,从而指定自身recv()方法中size的大小,解决黏包问题。

代码示例1:

1 import   socket 2 import subprocess 3 import json 4 import struct 5 server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 6 ip_port = ('127.0.0.1',8855) 7 server.bind(ip_port) 8 server.listen(5) 9 while True:10     con,add = server.accept()11     print(con)12     print(add)13     while True:14         try:15             data_bytes = con.recv(1024)16             if not data_bytes:break17             cmd = subprocess.Popen(data_bytes.decode('utf-8'),shell=True,18                                    stdout=subprocess.PIPE,19                                    stderr=subprocess.PIPE)20             #从管道读出的数据都是bytes类型,因此在发送到客户端时不需要编码21             std_out =  cmd.stdout.read()22             std_err =  cmd.stderr.read()23             data_size = len(std_out) + len(std_err)24             #定制报头25             head_dic = {
'data_size':data_size}26 # 报头处理27 head_str = json.dumps(head_dic)28 head_bytes = head_str.encode('utf-8')29 head_len = len(head_str)30 head_size = struct.pack('i',head_len)31 # 发送报头长度(发送4个字节)32 con.send(head_size)33 #发送报头数据34 con.send(head_bytes)35 # 发送数据36 con.send(std_out)37 con.send(std_err)38 except Exception:39 break40 con.close()41 server.close()
服务端
1 import  socket 2 import struct 3 import  json 4 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 5 ip_port = ('127.0.0.1',8855) 6 client.connect(ip_port) 7 while True: 8     msg = input('>>>:') 9     if not msg:continue10     client.send(msg.encode('gbk'))11     #part 1 收报头长度12     head_bytes = client.recv(4)13     head_len = struct.unpack('i',head_bytes)[0]14     #part 2 收报头数据15     dic_bytes = client.recv(head_len)16     head_str = dic_bytes.decode('gbk')17     head_dic = json.loads(head_str)18     data_size = head_dic['data_size']19     print(data_size)20     #part 3 收数据21         #统计每次循环取数据的长度22     recv_size = 023         #累计循环收到的数据24     recv_bytes = b''25     while recv_size < data_size :26         data = client.recv(1024)27         recv_size = recv_size + len(data)28         recv_bytes = recv_bytes + data29     print(recv_bytes.decode('gbk'))30 client.close()
客户端

 

转载于:https://www.cnblogs.com/liuyinzhou/p/7966777.html

你可能感兴趣的文章
流程控制 Day06
查看>>
Linux下安装Tomcat
查看>>
windows live writer 2012 0x80070643
查看>>
tomcat 和MySQL的安装
查看>>
git常用操作
查看>>
京东SSO单点登陆实现分析
查看>>
u-boot启动第一阶段
查看>>
MySQL批量SQL插入性能优化
查看>>
定义列属性:null,default,PK,auto_increment
查看>>
用户画像展示
查看>>
C#中StreamReader读取中文出现乱码
查看>>
使用BufferedReader的时候出现的问题
查看>>
批处理文件中的路径问题
查看>>
hibernate出现No row with the given identifier exists问题
查看>>
为什么wait()和notify()属于Object类
查看>>
配置NRPE的通讯
查看>>
匹配两个空格之间的字符。。。
查看>>
CSS 文字溢出 变成省略号 ...
查看>>
Spring事务
查看>>
java编程基础(三)流程控制语句
查看>>