首先,我们回顾一下 TCP 和 UDP 的头部信息:

具体说明看:http://www.cnblogs.com/aomi/p/7776582.html

我们知道,TCP 和 UDP 是 TCP/IP 协议族传输层中的两个具有代表性的协议。其中,TCP 是面向连接的复杂的、可靠的字节流传输协议,而 UDP 是面向无连接的简单的、不可靠的数据报传输协议。 
  “流”的概念就是指不间断的数据结构,可以把它想象成你们家里的自来水管道中的水流。什么意思呢?举个例子:TCP 发送端应用程序发送了10次100字节的消息,那么,在接收端的应用程序接收到的可能是一个1000字节的连续不间断的数据。但如果是 UDP 端口发送了一个100字节的消息,那么 UDP 接收端就会以100字节的长度来接收数据。正因为这样,我们可以看到 TCP 头部中并没有长度信息,而 UDP 头部包含长度信息。好了,现在你应该明白我们在创建套接字的时候,为什么 type 的类型是 SOCK_STREAM 和 SOCK_DGRAM 了吧! 
  

正如文章标题所述,显然,你已经知道 UDP 数据包存在明确边界,是不存在粘包现象的,只有 TCP 才会出现粘包现象。那么,接下来我们逐步分析 TCP 的流传输特性所带来如粘包这样的一些问题及其解决方案。

  按每次通信后是否闭关连接,可以分为两类情况:长连接和短连接。长连接——指的是客户端和服务端先建立通信连接,连接建立后不断开,然后再进行报文发送和接收。短连接——指的是客户端和服务端每进行一次报文收发交易时才进行通信连接,交易完毕后立即断开连接,比如 http 协议。 
  所以我们可以分析以下几种情况: 
  (1)如果利用 TCP 每次发送数据,就与对方建立连接,然后双方发送完一段数据后,就关闭连接,这样就不会出现粘包问题(因为只有一种数据结构)。 
  (2)如果发送数据无结构,如文件传输,这样发送端只管发送,接收端只管接收存储就行,也不用考虑粘包。 
  (3)如果双方建立连接,需要在连接后一段时间内发送多个不同结构的数据,这时候接收端收到就可能是一堆粘在一起的数据,这样接收端应用程序就傻了,到底是要干嘛?不知道,因为协议并没有规定这么诡异的数据。 
   
  那么,可以认为 TCP 粘包问题并不是对所有应用都造成困扰的,只是对那些长连接并且需要传输多种数据结构的应用造成影响。仔细分析会发现,除了粘包问题,其实还可能会出现多包、少包、半包、断包等情况。

针对这些问题,一般会有如下解决方法: 
  (1)调用发送函数之后都强制数据立即传送(PUSH 指令)。 
  (2)对于接收端引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象。 
  (3)添加一个固定的消息头,该消息头包含数据长度信息,每次数据时先接收固定大小的消息头,再根据其携带的长度信息接收消息实体。也就是说,通过人为控制多次接收来避免粘包。 
  (4)设置 TCP_NODELAY 选项,禁止 Nagle 算法。 
  (5)设置 SO_RCVBUF 和 SO_SNDBUF 选项,根据应用需求修改一个合适的接收、发送缓冲区大小。 
  (6)添加报文分隔标识,比如发送报文是在末尾添加 '\n' ,同时接收端使用 recv() 函数接收报文,并且设置参数 flags 的值为 MSG_PEEK。注意:当 flags 参数的值设置为 MSG_PEEK 时,recv() 可以从 socket 缓存中读取数据,但是不会将缓存中该部分数据清除,但如果使用 read() 函数直接读取 socket 缓存区中的内容,会清空缓存区中的内容。假设两段报文粘包,read() 会清空缓存区中所有内容,从而导致后一段报文中的粘包的部分数据丢失。

  实际上,上述的几种解决方法都有不足之处,并且不一定能够完全避免 TCP 粘包问题。所以还是需要根据实际应用来进行应用场景和性能方面的衡量。

 
1

TCP 粘包及其解决方案(zz)的更多相关文章

  1. python中TCP粘包问题解决方案

    TCP协议中的粘包问题 1.粘包现象 基于TCP写一个远程cmd功能 #服务端 import socket import subprocess sever = socket.socket() seve ...

  2. Netty4实战 - TCP粘包&拆包解决方案

    Netty是目前业界最流行的NIO框架之一,它的健壮性.高性能.可定制和可扩展性在同类框架中都是首屈一指.它已经得到了成百上千的商业项目的验证,例如Hadoop的RPC框架Avro就使用了Netty作 ...

  3. Socket编程(4)TCP粘包问题及解决方案

    ① TCP是个流协议,它存在粘包问题 TCP是一个基于字节流的传输服务,"流"意味着TCP所传输的数据是没有边界的.这不同于UDP提供基于消息的传输服务,其传输的数据是有边界的.T ...

  4. TCP粘包问题及解决方案

    ① TCP是个流协议,它存在粘包问题 TCP是一个基于字节流的传输服务,"流"意味着TCP所传输的数据是没有边界的.这不同于UDP提供基于消息的传输服务,其传输的数据是有边界的.T ...

  5. 【游戏开发】网络编程之浅谈TCP粘包、拆包问题及其解决方案

    引子 现如今手游开发中网络编程是必不可少的重要一环,如果使用的是TCP协议的话,那么不可避免的就会遇见TCP粘包和拆包的问题,马三觉得haifeiWu博主的 TCP 粘包问题浅析及其解决方案 这篇博客 ...

  6. 查漏补缺:socket编程:TCP粘包问题和常用解决方案(上)

    1.TCP粘包问题的产生(发送端) 由于TCP协议是基于字节流并且无边界的传输协议,因此很容易产生粘包问题.TCP的粘包可能发生在发送端,也可能发生在接收端.发送端的粘包是TCP协议本身引起的,TCP ...

  7. 深入了解Netty【八】TCP拆包、粘包和解决方案

    1.TCP协议传输过程 TCP协议是面向流的协议,是流式的,没有业务上的分段,只会根据当前套接字缓冲区的情况进行拆包或者粘包: 发送端的字节流都会先传入缓冲区,再通过网络传入到接收端的缓冲区中,最终由 ...

  8. TCP粘包问题的解决方案01——自定义包体

      粘包问题:应用层要发送数据,需要调用write函数将数据发送到套接口发送缓冲区.如果应用层数据大小大于SO_SNDBUF,那么,可能产生这样一种情况,应用层的数据一部分已经被发送了,还有一部分还在 ...

  9. TCP 粘包 - 拆包问题及解决方案

    目录 TCP粘包拆包问题 什么是粘包 - 拆包问题 为什么存在粘包 - 拆包问题 粘包 - 拆包 演示 粘包 - 拆包 解决方案 方式一: 固定缓冲区大小 方式二: 封装请求协议 方式三: 特殊字符结 ...

随机推荐

  1. ssh问题_2

    前一段时间配置hadoop集群环境,发现一个现象,教程中的命令形式是ssh hostname,当然这个hostname应该是在ssh发起者的hosts文件中和相应的IP对应:现在问题来了: 我用的是m ...

  2. PokeCats开发者日志(七)

      现在是PokeCats游戏开发的第十二天的晚上,很不幸提交到的三个平台(360开放平台,腾讯开放平台,华为应用市场)都没通过,著作权申请也被打回来了.   心中一万只草泥马在奔腾.   得了,看来 ...

  3. vsCode怎么为一个前端项目配置ts的运行环境

    vsCode为一个前端项目配置ts的运行环境,ts文件保存的时候自动编译成js文件: 假设此前端项目名称为Web:文件结构如图 1. 在根目录中新建一个“.vscode”文件夹,里面建一个“tasks ...

  4. asp.net中的cookie

    一.cookie导读,理解什么是cookie 1.什么是cookie:cookie是一种能够让网站服务器把少量数据(4kb左右)存储到客户端的硬盘或内存.并且读可以取出来的一种技术. 2.当你浏览某网 ...

  5. Foundation框架-NSCalendar

    NSCalendar 日历类 Cocoa中对日期和时间的处理 NSCalendar (一) (2008-11-12 21:54:10) NSCalendar用于处理时间相关问题.比如比较时间前后.计算 ...

  6. Linux和Windows上实现的异同-Linux的自适应ACK

    上周有同事问,延迟ACK到底对应用层会产生什么后果,我也不知道该如何作答,于是丢了一个链接: TCP之Delay ACK在Linux和Windows上实现的异同-Linux的自适应ACK: 是的,这是 ...

  7. [Leetcode] Linked list cycle ii 判断链表是否有环

    Given a linked list, return the node where the cycle begins. If there is no cycle, returnnull. Follo ...

  8. 安徽师大附中%你赛day4T1 金字塔 解题报告

    金字塔 题目背景: \(Zdrcl\)带着妹子们来到了胡夫金字塔周边旅游, 发现这里正在进行一个有关金字塔的游戏 题目描述: 游戏规则如下: 1. 这里的金字塔是一个 \(N\) 阶的二维金字塔. 2 ...

  9. cookie 是存储于访问者的计算机中的变量

    今天把javascript如何用来创建及存储cookie复习了一下,其中的一点体会拿出来和大家讨论,首先看一下基础知识: 什么是cookie cookie 是存储于访问者的计算机中的变量.每当同一台计 ...

  10. HDU3038:How Many Answers Are Wrong(带权并查集)

    How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...