socket模块粘包现象理解以及解决思路

粘包现象:

  • 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的。因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小、数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制

  • 对于UDP,不会使用块的合并优化算法,这样,实际上目前认为,是由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。所以UDP不会出现粘包问题。

粘包现象理解:

socket模块sned以及recv实现底层原理
  • send
    • 作用:将内存中的数据通过网卡发送出去
    • 底层原理:将数据从程序内存中拷贝到操作系统,通过操作系统调用网卡接口发送到远程
  • recv
    • 作用:接收远程发送的数据,传入参数单位为字节
    • 底层原理:网卡接收远程发过来的数据,然后将数据从操作系统内存拷贝到应用程序内存中

不管是recv还是send都不是直接发送或者接收对方的数据,而是操作自己的操作系统的内存,并且不是一个send对应一个recv,是根据recv接收数据的大小而决定

TCP协议传输优化算法:Nagle算法
  • 将数据比较小的包,并且时间间隔很短的包合并成一个包,调一次网卡io将数据发送到远程,节省调用网卡io的时间,粘包现象是TCP底层传输优化算法造成的。

粘包现象结局思路

  1. 客户端循环接收数据,使用while循环判断数据是否接收完毕
  2. 服务端返回诗句是打包报头发送给客户端,客户端根据报头发送的数据长度截取发送数据的真实长度
服务端:
  1. 制作固定长度的报头
  2. 将报头打包发送给客户端(使用struct模块打包数据)
  3. 再发送真实数据,通过while循环判断是否接收完毕,接收完了则跳出循环
客户端
  1. 接收报头,指定接收报头的长度,使用struct打包将服务端发送的报头按照指定模式解析
  2. 解析报头获得真实数据的长度描述

可使用内置模块struct打包与解析数据长度,

  1. i模式:4个字节长度
  2. l模式:8个字节长度
posted @ 2018-10-14 18:23  Wualin  阅读(451)  评论(0编辑  收藏  举报