第一个需要讨论的大概就是粘包问题了。因为这个是TCP的个性问题,UDP通信时不存在这个问题的。首先看一下什么叫粘包:

客户端采取与服务器的长连接方式建立通信(Open-Write/Read-Write/Read-……-Write/Read-Close)。即建立连接之后进行多次读写操作,最后才关闭。而且不是文件传输,而是数据结构的传输(文件传输发生粘包与没发生粘包都不会影响结果,反正都是字节流的按顺序写入本地文件)。举个例子来说明一下吧:

两种数据结构:{give me something} {don't give me anything}则粘包是则是接受到{give me something don't give me anything} 这个算是让服务器傻眼了,没见过这么诡异的数据结构,不知道怎么处理了。

上面的例子是转的网上的

来分析一下之所以发生粘包的原因吧,其实也就是为什么TCP会发生,但是UDP却不会发生的原因:TCP是面向连接流式无边界的传输方式。当传输通道建立之后,则数据流就像水一样流过来,其中没有数据边界的概念,包随便多大,因而会出现多个包最后粘成一个大包。当然这个是TCP的原因,还有就是缓冲区机制的问题,发送端在默认状况下是需要等到发送去满才发送出去,故而适当使用push刷缓冲区也可减少粘包的现象,还有就是接受缓冲区处理不及时,没有做到来一个包立马处理完这个包。

所以解决的思路大约如下:

  1. 对于发送方引起的粘包现象,用户可通过编程设置来避免,TCP提供了强制数据立即传送的操作指令push,TCP软件收到该操作指令后,就立即将本段数据发送出去,而不必等待发送缓冲区满。此种方法关闭了优化算法,降低了网络发送效率,影响应用程序的性能。而且并不能保证100%不发生粘包现象。
  2. 对于接收方引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象。该种思路对于接收方的程序算法结构要求较高,而且可靠性不高,因为网络通信中的并发等现象大量存在,很难真的能完全即使处理接受缓冲区而不发生粘包。
  3. 由接收方控制,将一包数据按结构字段,人为控制分多次接收,然后合并,通过这种手段来避免粘包。该思路的问题就更大了,应用程序效率被降低太多。而且我实在不认为这个真能不发生粘包,虽然包变小了,但是并发情况的存在并不能保证接收方有足够的间隙去处理包。
  4. 预定义数据结构,单线程。字节流前面先加上包头标志位,包头中包含该包的数据长度,这样在读取的时候可按字节读取。这样可有效控制粘包问题。并可以成功避免残包的问题,且不会发生连锁反应,一个坏包的出现不会影响下一个包的正常读取。如{##Length##DataStram}。该中解决方案的优点是可以保证通信的100%准确,缺点是影响程序性能,因为按字节读取包,必定会影响程序的效率。
  5. 改进:预定义数据结构,单线程。但是不是按字节。查看头标志位,读取包长度,查看缓冲区内包长度,两者相等,则直接读取。如果缓冲区内可读字节数大于标志位描述的包长度,则按照标志位描述的包长度读取数据,如果缓冲区内刻度字节数小于标志位描述的包长度,则线程睡眠,等下一个数据包的到来。
  6. 预定义数据结构,多线程。服务器端与客户端都是多线程工作,客户端为三个主要线程:发送线程、读取线程与解析线程。服务器端为四个主要线程:监听主线程、接收、读取、解析。按照第五种的思路,拿到数据包之后直接扔给解析线程,解析线程负责数据解析以及最终结果的回调。此处比第五种多的思路就是一个多线程,从而可以很大幅度提升程序的性能。                                                                       

    预定义数据结构示意图:

    标志位

    长度

    数据

    参考链接:

http://blog.csdn.net/laoyang360/article/details/8675922

http://www.cnblogs.com/BLoodMaster/archive/2010/07/02/1770067.html

TCP连接,传输数据时的粘包问题讨论的更多相关文章

  1. C#网络编程学习(5)---Tcp连接中出现的粘包、拆包问题

    本文参考于CSDN博客wxy941011 1.疑问 我们使用第四个博客中的项目. 修改客户端为:连接成功后循环向服务器发送从1-100的数字.看看服务器会不会正常的接收100次数据. 可是我们发现服务 ...

  2. Socket 编程中,TCP 流的结束标志与粘包问题

    因为 TCP 本身是无边界的协议,因此它并没有结束标志,也无法分包. socket和文件不一样,从文件中读,读到末尾就到达流的结尾了,所以会返回-1或null,循环结束,但是socket是连接两个主机 ...

  3. UNIX网络编程——tcp流协议产生的粘包问题和解决方案

    我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...

  4. tcp流协议产生的粘包问题和解决方案

    我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...

  5. python 之网络编程(基于TCP协议Socket通信的粘包问题及解决)

    8.4 粘包问题 粘包问题发生的原因: 1.发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包),这样接收端,就难于分辨出来了,必须提供科学的拆包机制. ...

  6. Go语言网络通信---tcp上传大文件(粘包问题还需优雅解决)

    server端: package main import ( "bufio" "encoding/binary" "fmt" "n ...

  7. tcp协议传输中的粘包问题

    什么是粘包问题 tcp是流体协议. 其nagle算法会将数据量较小. 并且发送间隔时间较短的多个数据包合并为一个发送. 网络传输的时候是一段一段字节流的发送. 在接收方看来根本不知道字节流从何开始. ...

  8. TCP 远程执行CMD (解决粘包问题) 代码

    服务端 from socket import * import subprocess,json,struct server= socket(AF_INET,SOCK_STREAM) server.bi ...

  9. TCP粘包问题

    1.什么是粘包? 粘包指的是数据与数据之间没有明确的分界线,导致不能正确的读取数据.换句话说就是接收方不知道发送方一次到底发送了多少数据.只有TCP才会出现粘包现象,UDP不会出现粘包现象,因为TCP ...

随机推荐

  1. HDU 1003 Max Sum && HDU 1231 最大连续子序列 (DP)

    Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  2. GSS4 2713. Can you answer these queries IV 线段树

    GSS7 Can you answer these queries IV 题目:给出一个数列,原数列和值不超过1e18,有两种操作: 0 x y:修改区间[x,y]所有数开方后向下调整至最近的整数 1 ...

  3. sgu 185 最短路建网络流

    题目:给出一个图,从图中找出两条最短路,使得边不重复. 分析:既然是最短路,那么,两条路径上的所有节点的入边(s,x).出边(x,e)必定是最优的,即 dis[x] = dis[s]+edge_dis ...

  4. 转: android app进程保活的文章列表

    1. Android 后台任务型App多进程架构演化 http://www.jianshu.com/p/4ac1f373e8cd 2. 关于 Android 进程保活,你所需要知道的一切 http:/ ...

  5. 【CSS3】---嵌入字体@font-face

    @font-face能够加载服务器端的字体文件,让浏览器端可以显示用户电脑里没有安装的字体. 语法: @font-face { font-family : 字体名称; src : 字体文件在服务器上的 ...

  6. C# 短信猫(SMS cat) 操作源码开发经验

    我曾经开发的某项目需要使用短信猫模块,要求使用C#编程操作.能独立使用的动态链接库之一就是网上流传的sms.dll,但它的功能较少,不能满足需求,鉴于一时找不到合适的完整代码,我深入研究了短信协议,借 ...

  7. Part 64 to 66 Talking about Indexers in C#

    Part 64 - C# Tutorial - How and where are indexers used in .net Part 65 - C# Tutorial - Indexers in ...

  8. DOS批处理命令-for语句

    for是为了循环执行一系列命令而执行的命令语句. for要处理的内容不同,语法结构稍有不同.下面就各种情形来分别 1.基本的语法:FOR %変数 IN (set) DO 命令 [参数] 语法内容解析: ...

  9. [Fiddler]Unable to Generate Certificate

    I'm using Fiddler2 (or trying) to capture SSL traffic for a windows desktop gadget hitting an https ...

  10. php删除数组中相同的元素,只保留一个相同元素

    <?php// 删除数组中相同元素,只保留一个相同元素function formatArray($array){sort($array);$tem = ”;$temarray = array() ...