TCP连接,传输数据时的粘包问题讨论
第一个需要讨论的大概就是粘包问题了。因为这个是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刷缓冲区也可减少粘包的现象,还有就是接受缓冲区处理不及时,没有做到来一个包立马处理完这个包。
所以解决的思路大约如下:
- 对于发送方引起的粘包现象,用户可通过编程设置来避免,TCP提供了强制数据立即传送的操作指令push,TCP软件收到该操作指令后,就立即将本段数据发送出去,而不必等待发送缓冲区满。此种方法关闭了优化算法,降低了网络发送效率,影响应用程序的性能。而且并不能保证100%不发生粘包现象。
- 对于接收方引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象。该种思路对于接收方的程序算法结构要求较高,而且可靠性不高,因为网络通信中的并发等现象大量存在,很难真的能完全即使处理接受缓冲区而不发生粘包。
- 由接收方控制,将一包数据按结构字段,人为控制分多次接收,然后合并,通过这种手段来避免粘包。该思路的问题就更大了,应用程序效率被降低太多。而且我实在不认为这个真能不发生粘包,虽然包变小了,但是并发情况的存在并不能保证接收方有足够的间隙去处理包。
- 预定义数据结构,单线程。字节流前面先加上包头标志位,包头中包含该包的数据长度,这样在读取的时候可按字节读取。这样可有效控制粘包问题。并可以成功避免残包的问题,且不会发生连锁反应,一个坏包的出现不会影响下一个包的正常读取。如{##Length##DataStram}。该中解决方案的优点是可以保证通信的100%准确,缺点是影响程序性能,因为按字节读取包,必定会影响程序的效率。
- 改进:预定义数据结构,单线程。但是不是按字节。查看头标志位,读取包长度,查看缓冲区内包长度,两者相等,则直接读取。如果缓冲区内可读字节数大于标志位描述的包长度,则按照标志位描述的包长度读取数据,如果缓冲区内刻度字节数小于标志位描述的包长度,则线程睡眠,等下一个数据包的到来。
- 预定义数据结构,多线程。服务器端与客户端都是多线程工作,客户端为三个主要线程:发送线程、读取线程与解析线程。服务器端为四个主要线程:监听主线程、接收、读取、解析。按照第五种的思路,拿到数据包之后直接扔给解析线程,解析线程负责数据解析以及最终结果的回调。此处比第五种多的思路就是一个多线程,从而可以很大幅度提升程序的性能。
预定义数据结构示意图:
标志位
长度
数据
参考链接:
http://blog.csdn.net/laoyang360/article/details/8675922
http://www.cnblogs.com/BLoodMaster/archive/2010/07/02/1770067.html
TCP连接,传输数据时的粘包问题讨论的更多相关文章
- C#网络编程学习(5)---Tcp连接中出现的粘包、拆包问题
本文参考于CSDN博客wxy941011 1.疑问 我们使用第四个博客中的项目. 修改客户端为:连接成功后循环向服务器发送从1-100的数字.看看服务器会不会正常的接收100次数据. 可是我们发现服务 ...
- Socket 编程中,TCP 流的结束标志与粘包问题
因为 TCP 本身是无边界的协议,因此它并没有结束标志,也无法分包. socket和文件不一样,从文件中读,读到末尾就到达流的结尾了,所以会返回-1或null,循环结束,但是socket是连接两个主机 ...
- UNIX网络编程——tcp流协议产生的粘包问题和解决方案
我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...
- tcp流协议产生的粘包问题和解决方案
我们在前面曾经说过,发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据,也就是说,应用程序所看到的数据是一个整体 ...
- python 之网络编程(基于TCP协议Socket通信的粘包问题及解决)
8.4 粘包问题 粘包问题发生的原因: 1.发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包),这样接收端,就难于分辨出来了,必须提供科学的拆包机制. ...
- Go语言网络通信---tcp上传大文件(粘包问题还需优雅解决)
server端: package main import ( "bufio" "encoding/binary" "fmt" "n ...
- tcp协议传输中的粘包问题
什么是粘包问题 tcp是流体协议. 其nagle算法会将数据量较小. 并且发送间隔时间较短的多个数据包合并为一个发送. 网络传输的时候是一段一段字节流的发送. 在接收方看来根本不知道字节流从何开始. ...
- TCP 远程执行CMD (解决粘包问题) 代码
服务端 from socket import * import subprocess,json,struct server= socket(AF_INET,SOCK_STREAM) server.bi ...
- TCP粘包问题
1.什么是粘包? 粘包指的是数据与数据之间没有明确的分界线,导致不能正确的读取数据.换句话说就是接收方不知道发送方一次到底发送了多少数据.只有TCP才会出现粘包现象,UDP不会出现粘包现象,因为TCP ...
随机推荐
- leetcode 题解:Binary Tree Inorder Traversal (二叉树的中序遍历)
题目: Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary ...
- iOS - UI - UIWebView
1.UIWebView UIWebView 是 苹果提供的用来展示网页的UI控件.它也是最占内存的控件. iOS8.0 webkit框架. WKWebView,相比UIWebView,节省了1/3~1 ...
- 《Cortex-M0权威指南》之Cortex-M0编程入门
转载请注明来源:cuixiaolei的技术博客 嵌入式系统编程入门 微控制器是如何启动的 为了保存编译号的二进制程序代码,大多数的现代微控制器都会包含片上flash存储器.有些微控制器还可能有一个独立 ...
- Java学习笔记——多态性Polymorphism
Java中实现多态的机制 Java中实现多态的机制靠的是父类或者接口定义的引用变量可以指向子类或者具体的实现类的实例对象,而程序调的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就 ...
- QQ互联登陆出现(1054) Unknown column “conuintoken” in “field list”
在dz论坛中打开了QQ互联登录功能之后提示(1054) Unknown column conuintoken in field list 错误 我们看到sql 错误就是说没有conuintoken字了 ...
- UISearchDisplayController隐藏navigationBar需注意
不能调用self.navigationController.navigationBar.hidden = YES: 调用此代码的话,你隐藏了navigationBar搜索展示控制器就拿不到导航条:就会 ...
- Linux 网卡驱动设备程序设计(1)
一.网卡驱动架构分析 1. Linux 网络子系统 #系统调用接口层 为应用程序提供访问网络子系统的统一方法. #协议无关层 提供通用的方法来使用传输层协议. #协议栈的实现 实现具体的网络协议 #设 ...
- Linux勉強
block 與 inode 的總量: 未使用與已使用的 inode / block 數量: block 與 inode 的大小 (block 為 1, 2, 4K,inode 為 128 by ...
- Backbone.js学习之初识hello-world
说了好久好久要学习Backbone.js,现在终于下定决心开始学习了.然后呢,就根据我的学习进度在这里做个简单的记录,方便新人,也方便我自己以后回忆. 准备 用bower下载这几个库或框架也是醉了.. ...
- 每天一道LeetCode--58. Length of Last Word
Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...