网络编程之粘包(代码片段)

robert-zhou robert-zhou     2023-02-14     140

关键词:

粘包:
传输层协议有tcp和udp两种
tcp:Transmission Control Protocol
传输控制协议,基于数据流,收发的消息不能为空,需要在客户端和服务端都添加空消息的处理机制
tcp是可靠性协议,数据的收发都需要确认信息,这就降低了传输效率,故为了减少确认次数,tcp采用了nagle算法
将多次间隔短且数据小的数据合成一个数据流,然后发送,tcp的数据没有明确的界限,无法区分数据的开始和结束,
这就导致了可能将多个信息并为一条信息,也就是粘包
还有一种粘包情况是当一个数据包过大时,操作系统的缓存只会提供一部分数据给应用程序,导致我们只读了包的一部分内容,其余内容当我们再次接收时会发送过来

综上 tcp粘包问题的产生,是因为传输数据没有具体的界限,所以解决粘包问题需要知道数据的明确长度,当长度小时我们明确接受该长度的数据,当长度过大时,我们采用循环接受的方法来取

具体操作:1.发送方获取消息的具体长度
2.发送方先将该长度发送给接收方
3.接收方通过此长度准确接收消息
上述操作使用了第三方模块struct
struct的作用,pack方法将一个整数,转换成固定长度的bytes类型
unpack方法将一个bytes类型的长度转换为整数
解决粘包问题的核心,给数据流添加自定义报头
报头可以存放发送时间,真实信息大小,通过json模块保存成字典或列表,以便我们可以更方便的取值
具体代码(以cmd实现客户端系统命令为例子):

服务端

from socket import *
import json
import struct
import subprocess
import datetime
s = socket()#创建套接字对象
s.bind(("127.0.0.1",8888))#绑定ip和端口
s.listen(5)#监听,规定半连接池大小
while True:
    conn,addr = s.accept()#接收客户端连接,三次握手
    while True:
        try:
            cmd = conn.recv(1024)#接收cmd命令
            if not cmd:#linux系统客户端强退时会不停发空消息,故此处为防止客户端突然退出,跨平台性
                conn.close()
                break
            obj  = subprocess.Popen(cmd.decode("utf-8"),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)#使用subprocess模块完成系统命令
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()
            msg = stdout +stderr

            s_dic = #自定义报头
            s_dic["time"] = str(datetime.datetime.now())#添加key  time
            s_dic["size"] = len(msg)#添加key size
            head_data = json.dumps(s_dic)#使用json序列化成json格式的字符串
            head_len = struct.pack("i",len(head_data))#使用struct模块获取报头长度,将整形转换为二进制,固定为4个字节大小
            conn.send(head_len)#先发送报头长,此时使用的“i”模式为4字节,故客户端以4个字节接收,接收后使用struct模块反解出报头信息长准确接收报头信息,
#防止报头信息和具体信息粘包
            conn.send(head_data.encode("utf-8"))#将json格式的字符串转换成二进制,发送报头信息,报头信息的作用,客户端可以通过报头信息获取具体信息长度
            conn.send(msg)#发送具体信息
        except ConnectionResetError:
            conn.close()
            break
客户端:
     c = socket()#创建客户端套接字对象
     c.connect(("127.0.0.1",8888))#链接服务器

 while True:
     cmd = input(">>>:").strip().encode("utf-8")#接收命令
     c.send(cmd)#发送命令给服务器
     lenth = c.recv(4)#接收报头长度
     head_lenth = struct.unpack("i",lenth)[0]#unpack出整形报头信息的长度
     head_data = c.recv(head_lenth)#准确接收报头信息
     dic = json.loads(head_data.decode("utf-8"))#获取报头信息
     print(dic)
     rev_size = 0
     all_data = b""
     while rev_size < dic["size"]:#由报头信息或得的具体信息长
         data = c.recv(1024)#循环接收
         rev_size += len(data)
         all_data += data

     print(all_data.decode("gbk"))

udp协议
user datagram protocol,用户数据报协议
没有链接,面向消息,效率高,udp数据包有报头,故不会产生粘包问题


















网络编程之粘包问题使用socketserver实现并发(代码片段)

一、粘包问题注意:粘包问题只有tcp协议并且udp协议永远不会粘包粘包问题的产生:简述:粘包问题的产生主要是由于tcp协议传输数据(其内置的nagle算法来进行的)会将数据较小的且发送时间较短的合并成一个包从发送端发送... 查看详情

网络编程之粘包(代码片段)

粘包:传输层协议有tcp和udp两种tcp:TransmissionControlProtocol传输控制协议,基于数据流,收发的消息不能为空,需要在客户端和服务端都添加空消息的处理机制tcp是可靠性协议,数据的收发都需要确认信息,这就降低了传输效率,... 查看详情

netty之粘包拆包bytetomessagedecoder(代码片段)

目录拆包粘包处理的方式netty的处理方式netty实现编码解码1、cumulator.cumulate()拼接数据包2、callDecode()解析数据包总结LengthFieldBasedFrameDecoder拆包粘包粘包产生的原因:两个包小于缓存区的大小,传送数据会将两个包都放在... 查看详情

netty之粘包拆包bytetomessagedecoder(代码片段)

目录拆包粘包处理的方式netty的处理方式netty实现编码解码1、cumulator.cumulate()拼接数据包2、callDecode()解析数据包总结LengthFieldBasedFrameDecoder拆包粘包粘包产生的原因:两个包小于缓存区的大小,传送数据会将两个包都放在... 查看详情

netty之粘包拆包bytetomessagedecoder(代码片段)

目录拆包粘包处理的方式netty的处理方式netty实现编码解码1、cumulator.cumulate()拼接数据包2、callDecode()解析数据包总结LengthFieldBasedFrameDecoder拆包粘包粘包产生的原因:两个包小于缓存区的大小,传送数据会将两个包都放在... 查看详情

socket网络编程之粘包问题详解(代码片段)

一,粘包问题详情1,只有TCP有粘包现象,UDP永远不会粘包   你的程序实际上无权直接操作网卡的,你操作网卡都是通过操作系统给用户程序暴露出来的接口,那每次你的程序要给远程发数据时,其实是先把数据从用户态co... 查看详情

socket之粘包

什么是粘包粘包是一种现象 这种现象只出现在TCP中而不会出现在UDP中(TCP和UDP都是传输层中的协议)粘包:粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的粘包概念详解:当发... 查看详情

socket之粘包发生问题

粘包注意注意注意:res=subprocess.Popen(cmd.decode(‘utf-8‘),shell=True,stderr=subprocess.PIPE,stdout=subprocess.PIPE)的结果的编码是以当前所在的系统为准的,如果是windows,那么res.stdout.read()读出的就是GBK编码的,在接收端需要用GBK解码且只能从... 查看详情

第六章-网络编程-粘包(代码片段)

1.粘包:多个包多个命令的结果粘到一起了因为recv1024限制了导致的结果参考:http://www.cnblogs.com/linhaifeng/articles/6129246.html粘包底层原理分析:1.运行一个软件和哪几个硬件有关硬盘内存cpu2.启动程序:硬盘程序加载到内存启一个软... 查看详情

网络编程粘包问题(代码片段)

    首先说为什么会粘包,在py2上运行时,服务器把两次发送的操作强制的合成一次发送给客户端,所以粘在一起了,因为python3的版本是可以的,但是有的时候python3也会出现粘包现象。  解决粘包的问题有两种方法: ... 查看详情

网络编程基础粘包现象(代码片段)

粘包tcp是流式传输,字节流,数据与数据之间是没有边界的流式传输优点:不限定长度可靠传输缺点:慢和一个人的通信连接conn会一直占用我们的通信资源udp协议,面向数据包的传输数据包优点快由于不需要建立连接,所以谁... 查看详情

网络编程ssh,粘包(代码片段)

1.什么是socket?TCP,可靠地,面向连接协议,有阻塞rect udp,不可靠的,无线连接的服务这里因为不需要阻塞,所以速度会很快,但安全性不高2.关于客户端退出而服务器未退出的解决办法1importsocket2sock=socket.socket()#TCP协议3IP_PORT=("127.0.0.1"... 查看详情

网络编程——通信循环链接循环粘包问题(代码片段)

通信循环、链接循环、粘包问题一、通信循环服务端和客户端可以进行连续的信息交流fromsocketimport*ser_socket=socket(AF_INET,SOCK_STREAM)ser_socket.bind((‘127.0.0.1‘,8886))ser_socket.listen(5)conn,addr=ser_socket.accept()whileTrue:try:#抛出异常,若不抛 查看详情

java网络编程——粘包拆包出现的原因及解决方式(代码片段)

在基于TCP协议的网络编程中,不可避免地都会遇到粘包和拆包的问题。什么是粘包和拆包?先来看个例子,还是上篇文章《Java网络编程——NIO的阻塞IO模式、非阻塞IO模式、IO多路复用模式的使用》中“IO多路复用模式... 查看详情

java网络编程——粘包拆包出现的原因及解决方式(代码片段)

在基于TCP协议的网络编程中,不可避免地都会遇到粘包和拆包的问题。什么是粘包和拆包?先来看个例子,还是上篇文章《Java网络编程——NIO的阻塞IO模式、非阻塞IO模式、IO多路复用模式的使用》中“IO多路复用模式... 查看详情

使用newlife网络库管道模式解决数据粘包(代码片段)

...一个基本的Newlife网络服务端这边我们来讲一下如何解决粘包的问题在上一篇总我们注册了Newlife的管道处理器,我们来看看他是如何实现粘包处理的svr.Add<ReciveFilter>();//粘包处理管道首先看一下我们设备的上传数据协议 &n... 查看详情

socket编程(代码片段)

TCP下粘包问题两种情况下会发生粘包。1、发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)发送方:AB  #其实放在缓存里没发送发送方:B  #其实放在缓存里没发... 查看详情

网络编程(代码片段)

阅读目录一客户端/服务器架构二osi七层三socket层四socket是什么五套接字发展史及分类六套接字工作流程七基于TCP的套接字八基于UDP的套接字九粘包现象十什么是粘包十一解决粘包的low比处理方法十二峰哥解决粘包的方法十三认... 查看详情