zoukankan      html  css  js  c++  java
  • 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个字节长度
  • 相关阅读:
    [Luogu P3626] [APIO2009] 会议中心
    杭电 1869 六度分离 (求每两个节点间的距离)
    杭电 1874 畅通工程续 (求某节点到某节点的最短路径)
    最短路径模板
    杭电 2544 最短路径
    POJ 1287 Networking (最小生成树模板题)
    NYOJ 1875 畅通工程再续 (无节点间距离求最小生成树)
    POJ 2485 Highways (求最小生成树中最大的边)
    杭电 1233 还是畅通工程 (最小生成树)
    杭电 1863 畅通工程 (最小生成树)
  • 原文地址:https://www.cnblogs.com/wualin/p/9787287.html
Copyright © 2011-2022 走看看