化妆品产品的自建网站哟哪些,wordpress滑动图片,上海最近出啥事了,如何做网站怎么赚钱吗TCP通信粘包问题分析和解决#xff08;全#xff09;在socket网络程序中#xff0c;TCP和UDP分别是面向连接和非面向连接的。因此TCP的socket编程#xff0c;收发两端#xff08;客户端和服务器端#xff09;都要有成对的socket#xff0c;因此#xff0c;发送端为了将…TCP通信粘包问题分析和解决全在socket网络程序中TCP和UDP分别是面向连接和非面向连接的。因此TCP的socket编程收发两端客户端和服务器端都要有成对的socket因此发送端为了将多个发往接收端的包更有效的发到对方使用了优化方法Nagle算法将多次间隔较小、数据量小的数据合并成一个大的数据块然后进行封包。这样接收端就难于分辨出来了必须提供科学的拆包机制。对于UDP不会使用块的合并优化算法这样实际上目前认为是由于UDP支持的是一对多的模式所以接收端的skbuff(套接字缓冲区采用了链式结构来记录每一个到达的UDP包在每个UDP包中就有了消息头消息来源地址端口等信息这样对于接收端来说就容易进行区分处理了。所以UDP不会出现粘包问题。在介绍TCP之前先普及下两个相关的概念长连接和短连接。1.长连接Client方与Server方先建立通讯连接连接建立后 不断开 然后再进行报文发送和接收。2.短连接Client方与Server每进行一次报文收发交易时才进行通讯连接交易完毕后立即断开连接。此种方式常用于一点对多点通讯比如多个Client连接一个Server. TCP协议简介TCP是一个面向连接的传输层协议虽然TCP不属于ISO制定的协议集但由于其在商业界和工业界的成功应用它已成为事实上的网络标准广泛应用于各种网络主机间的通信。作为一个面向连接的传输层协议TCP的目标是为用户提供可靠的端到端连接保证信息有序无误的传输。它除了提供基本的数据传输功能外还为保证可靠性采用了数据编号、校验和计算、数据确认等一系列措施。它对传送的每个数据字节都进行编号并请求接收方回传确认信息ACK。发送方如果在规定的时间内没有收到数据确认就重传该数据。1 数据编号使接收方能够处理数据的失序和重复问题。2 数据误码问题通过在每个传输的数据段中增加校验和予以解决接收方在接收到数据后检查校验和若校验和有误则丢弃该有误码的数据段并要求发送方重传。3 流量控制也是保证可靠性的一个重要措施若无流控可能会因接收缓冲区溢出而丢失大量数据导致许多重传造成网络拥塞恶性循环。4 TCP采用可变窗口进行流量控制由接收方控制发送方发送的数据量。TCP为用户提供了高可靠性的网络传输服务但可靠性保障措施也影响了传输效率。因此在实际工程应用中只有关键数据的传输才采用TCP而普通数据的传输一般采用高效率的UDP。 保护消息边界和流那么什么是保护消息边界和流呢?保护消息边界就是指传输协议把数据当作一条独立的消息在网上传输接收端只能接收独立的消息。也就是说存在保护消息边界接收端一次只能接收发送端发出的一个数据包。而面向流则是指无保护消息保护边界的如果发送端连续发送数据接收端有可能在一次接收动作中会接收两个或者更多的数据包。例如我们连续发送三个数据包大小分别是2k4k 8k,这三个数据包都已经到达了接收端的网络堆栈中如果使用UDP协议不管我们使用多大的接收缓冲区去接收数据我们必须有三次接收动作才能够把所有的数据包接收完.而使用TCP协议我们只要把接收的缓冲区大小设置在14k以上我们就能够一次把所有的数据包接收下来只需要有一次接收动作。 注意这就是因为UDP协议的保护消息边界使得每一个消息都是独立的。而流传输却把数据当作一串数据流他不认为数据是一个一个的消息。所以有很多人在使用tcp协议通讯的时候并不清楚tcp是基于流的传输当连续发送数据的时候他们时常会认识tcp会丢包。其实不然因为当他们使用的缓冲区足够大时他们有可能会一次接收到两个甚至更多的数据包而很多人往往会忽视这一点只解析检查了第一个数据包而已经接收的其他数据包却被忽略了。所以大家如果要作这类的网络编程的时候,必须要注意这一点。 结论1TCP为了保证可靠传输尽量减少额外开销每次发包都要验证因此采用了流式传输面向流的传输相对于面向消息的传输可以减少发送包的数量从而减少了额外开销。但是对于数据传输频繁的程序来讲使用TCP可能会容易粘包。当然对接收端的程序来讲如果机器负荷很重也会在接收缓冲里粘包。这样就需要接收端额外拆包增加了工作量。因此这个特别适合的是数据要求可靠传输但是不需要太频繁传输的场合两次操作间隔100ms具体是由TCP等待发送间隔决定的取决于内核中的socket的写法2UDP由于面向的是消息传输它把所有接收到的消息都挂接到缓冲区的接受队列中因此它对于数据的提取分离就更加方便但是它没有粘包机制因此当发送数据量较小的时候就会发生数据包有效载荷较小的情况也会增加多次发送的系统发送开销系统调用写硬件等和接收开销。因此应该最好设置一个比较合适的数据包的包长来进行UDP数据的发送。UDP最大载荷为1472因此最好能每次传输接近这个数的数据量这特别适合于视频音频等大块数据的发送同时通过减少握手来保证流媒体的实时性粘包问题分析与对策TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包从接收缓冲区看后一包数据的头紧接着前一包数据的尾。出现粘包现象的原因是多方面的它既可能由发送方造成也可能由接收方造成。 什么时候需要考虑粘包问题1如果利用tcp每次发送数据就与对方建立连接然后双方发送完一段数据后就关闭连接这样就不会出现粘包问题因为只有一种包结构,类似于http协议。关闭连接主要是要双方都发送close连接参考tcp关闭协议。如A需要发送一段字符串给B那么A与B建立连接然后发送双方都默认好的协议字符如hello give me sth abour yourself然后B收到报文后就将缓冲区数据接收然后关闭连接这样粘包问题不用考虑到因为大家都知道是发送一段字符。2如果发送数据无结构如文件传输这样发送方只管发送接收方只管接收存储就ok也不用考虑粘包3如果双方建立连接需要在连接后一段时间内发送不同结构数据如连接后有好几种结构1)hellogive me sth abour yourself2)Dontgive me sth abour yourself那这样的话如果发送方连续发送这个两个包出去接收方一次接收可能会是hellogive me sth abour yourselfDont give me sth abour yourself这样接收方就傻了到底是要干嘛不知道因为协议没有规定这么诡异的字符串所以要处理把它分包怎么分也需要双方组织一个比较好的包结构所以一般可能会在头加一个数据长度之类的包以确保接收。 粘包出现原因简单得说在流传输中出现UDP不会出现粘包因为它有消息边界(参考Windows网络编程)1发送端需要等缓冲区满才发送出去造成粘包2接收方不及时接收缓冲区的包造成多个包接收具体点1发送方引起的粘包是由TCP协议本身造成的TCP为提高传输效率发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少通常TCP会根据优化算法把这些数据合成一包后一次发送出去这样接收方就收到了粘包数据。2接收方引起的粘包是由于接收方用户进程不及时接收数据从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区用户进程从该缓冲区取数据若下一包数据到达时前一包数据尚未被用户进程取走则下一包数据放到系统接收缓冲区时就接到前一包数据之后而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据这样就一次取到了多包数据。粘包情况有两种一种是粘在一起的包都是完整的数据包另一种情况是粘在一起的包有不完整的包。不是所有的粘包现象都需要处理若传输的数据为不带结构的连续流数据如文件传输则不必把粘连的包分开简称分包。但在实际工程应用中传输的数据一般为带结构的数据这时就需要做分包处理。在处理定长结构数据的粘包问题时分包算法比较简单在处理不定长结构数据的粘包问题时分包算法就比较复杂。特别是粘在一起的包有不完整的包的粘包情况由于一包数据内容被分在了两个连续的接收包中处理起来难度较大。实际工程应用中应尽量避免出现粘包现象。 为了避免粘包现象可采取以下几种措施1对于发送方引起的粘包现象用户可通过编程设置来避免TCP提供了强制数据立即传送的操作指令pushTCP软件收到该操作指令后就立即将本段数据发送出去而不必等待发送缓冲区满2对于接收方引起的粘包则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施使其及时接收数据从而尽量避免出现粘包现象3由接收方控制将一包数据按结构字段人为控制分多次接收然后合并通过这种手段来避免粘包。 以上提到的三种措施都有其不足之处。1第一种编程设置方法虽然可以避免发送方引起的粘包但它关闭了优化算法降低了网络发送效率影响应用程序的性能一般不建议使用。2第二种方法只能减少出现粘包的可能性但并不能完全避免粘包当发送频率较高时或由于网络突发可能使某个时间段数据包到达接收方较快接收方还是有可能来不及接收从而导致粘包。3第三种方法虽然避免了粘包但应用程序的效率较低对实时应用的场合不适合。 一种比较周全的对策是接收方创建一预处理线程对接收到的数据包进行预处理将粘连的包分开。对这种方法我们进行了实验证明是高效可行的。具体可以参考http://blog.csdn.net/soli/article/details/1297109 TCP无保护消息边界的解决针对这个问题一般有3种解决方案(1)发送固定长度的消息(2)把消息的尺寸与消息一块发送(3)使用特殊标记来区分消息间隔其解决方法具体解决可以参考http://blog.csdn.net/zhangxinrun/article/details/6721427 网络通讯的封包和拆包对于基于TCP开发的通讯程序有个很重要的问题需要解决就是封包和拆包。 为什么基于TCP的通讯程序需要进行封包和拆包TCP是个流协议所谓流就是没有界限的一串数据大家可以想想河里的流水是连成一片的其间是没有分界线的。但一般通讯程序开发是需要定义一个个相互独立的数据包的比如用于登陆的数据包用于注销的数据包。由于TCP流的特性以及网络状况在进行数据传输时会出现以下几种情况。假设我们连续调用两次send分别发送两段数据data1和data2,在接收端有以下几种接收情况(当然不止这几种情况,这里只列出了有代表性的情况).A.先接收到data1,然后接收到data2.B.先接收到data1的部分数据,然后接收到data1余下的部分以及data2的全部.C.先接收到了data1的全部数据和data2的部分数据,然后接收到了data2的余下的数据.D.一次性接收到了data1和data2的全部数据.对于A这种情况正是我们需要的,不再做讨论.对于B,C,D的情况就是大家经常说的粘包,就需要我们把接收到的数据进行拆包拆成一个个独立的数据包为了拆包就必须在发送端进行封包。另对于UDP来说就不存在拆包的问题,因为UDP是个数据包协议,也就是两段数据间是有界限的在接收端要么接收不到数据要么就是接收一个完整的一段数据不会少接收也不会多接收。 为什么会出现B.C.D的情况1.由Nagle算法造成的发送端的粘包:Nagle算法是一种改善网络传输效率的算法.简单的说,当我们提交一段数据给TCP发送时,TCP并不立刻发送此段数据,而是等待一小段时间,看看在等待期间是否还有要发送的数据,若有则会一次把这两段数据发送出去.这是对Nagle算法一个简单的解释,详细的请看相关书籍. C和D的情况就有可能是Nagle算法造成的.2.接收端接收不及时造成的接收端粘包:TCP会把接收到的数据存在自己的缓冲区中,然后通知应用层取数据.当应用层由于某些原因不能及时的把TCP的数据取出来,就会造成TCP缓冲区中存放了几段数据. 怎样封包和拆包最初遇到粘包的问题时,我是通过在两次send之间调用sleep来休眠一小段时间来解决。这个解决方法的缺点是显而易见的使传输效率大大降低而且也并不可靠。后来就是通过应答的方式来解决尽管在大多数时候是可行的但是不能解决B的那种情况而且采用应答方式增加了通讯量,加重了网络负荷. 再后来就是对数据包进行封包和拆包的操作。 封包封包就是给一段数据加上包头,这样一来数据包就分为包头和包体两部分内容了(以后讲过滤非法包时封包会加入包尾内容)。包头其实上是个大小固定的结构体其中有个结构体成员变量表示包体的长度这是个很重要的变量其他的结构体成员可根据需要自己定义。根据包头长度固定以及包头中含有包体长度的变量就能正确的拆分出一个完整的数据包。 拆包对于拆包目前我最常用的是以下两种方式1动态缓冲区暂存方式。之所以说缓冲区是动态的是因为当需要缓冲的数据长度超出缓冲区的长度时会增大缓冲区长度。大概过程描述如下:A,为每一个连接动态分配一个缓冲区,同时把此缓冲区和SOCKET关联,常用的是通过结构体关联.B,当接收到数据时首先把此段数据存放在缓冲区中.C,判断缓存区中的数据长度是否够一个包头的长度,如不够,则不进行拆包操作.D,根据包头数据解析出里面代表包体长度的变量.E,判断缓存区中除包头外的数据长度是否够一个包体的长度,如不够,则不进行拆包操作.F,取出整个数据包.这里的取的意思是不光从缓冲区中拷贝出数据包,而且要把此数据包从缓存区中删除掉.删除的办法就是把此包后面的数据移动到缓冲区的起始地址. 这种方法有两个缺点.1 为每个连接动态分配一个缓冲区增大了内存的使用.2 有三个地方需要拷贝数据,一个地方是把数据存放在缓冲区,一个地方是把完整的数据包从缓冲区取出来,一个地方是把数据包从缓冲区中删除.第二种拆包的方法会解决和完善这些缺点.前面提到过这种方法的缺点.下面给出一个改进办法, 即采用环形缓冲.但是这种改进方法还是不能解决第一个缺点以及第一个数据拷贝,只能解决第三个地方的数据拷贝(这个地方是拷贝数据最多的地方).第2种拆包方式会解决这两个问题.环形缓冲实现方案是定义两个指针,分别指向有效数据的头和尾.在存放数据和删除数据时只是进行头尾指针的移动. 2利用底层的缓冲区来进行拆包由于TCP也维护了一个缓冲区,所以我们完全可以利用TCP的缓冲区来缓存我们的数据这样一来就不需要为每一个连接分配一个缓冲区了。另一方面我们知道recv或者wsarecv都有一个参数,用来表示我们要接收多长长度的数据。利用这两个条件我们就可以对第一种方法进行优化。对于阻塞SOCKET来说我们可以利用一个循环来接收包头长度的数据然后解析出代表包体长度的那个变量再用一个循环来接收包体长度的数据。编程实现见http://blog.csdn.net/zhangxinrun/article/details/6721495这个问题产生于编程中遇到的几个问题1、使用TCP的Socket发送数据的时候会出现发送出错WSAEWOULDBLOCK在TCP中不是会保证发送的数据能够安全的到达接收端的吗也有窗口机制去防止发送速度过快为什么还会出错呢2、TCP协议在使用Socket发送数据的时候每次发送一个包接收端是完整的接受到一个包还是怎么样如果是每发一个包就接受一个包为什么还会出现粘包问题具体是怎么运行的3、关于Send是不是只有在非阻塞状态下才会出现实际发送的比指定发送的小在阻塞状态下会不会出现实际发送的比指定发送的小就是说只能出现要么全发送要么不发送在非阻塞状态下如果之发送了一些数据要怎么处理调用了Send函数后发现返回值比指定的要小具体要怎么做4、最后一个问题就是TCP/IP协议和Socket是什么关系是指具体的实现上Socket是TCP/IP的实现那么为什么会出现使用TCP协议的Socket会发送出错。这个问题第1个回答1应该是你的缓冲区不够大,2 tcp是流,没有界限.也就没所谓的包.3阻塞也会出现这种现象,出现后继续发送没发送出去的.4tcp是协议,socket是一种接口,没必然联系.错误取决于你使用接口的问题,跟tcp没关系.这个问题第2个回答1、应该不是缓冲区大小问题我试过设置缓冲区大小不过这里有个问题就是就算我把缓冲区设置成几G也返回成功不过实际上怎么可能设置那么大3、出现没发送完的时候要手动发送吧有没有具体的代码实现4、当选择TCP的Socket发送数据的时候TCP中的窗口机制不是能防止发送速度过快的吗为什么Socket在出现了WSAEWOULDBLOCK后没有处理这个问题第3个回答1.在使用非阻塞模式的情况下如果系统发送缓冲区已满并示及时发送到对端就会产生该错误继续重试即可。3.如果没有发完就继续发送后续部分即可。这个问题第4个回答1、使用非阻塞模式时如果当前操作不能立即完成则会返回失败错误码是WSAEWOULDBLOCK这是正常的程序可以先执行其它任务过一段时间后再重试该操作。2、发送与接收不是一一对应的TCP会把各次发送的数据重新组合可能合并也可能拆分但发送次序是不变的。3、在各种情况下都要根据send的返回值来确定发送了多少数据没有发送完就再接着发。4、socket是Windows提供网络编程接口TCP/IP是网络传输协议使用socket是可以使用多种协议其中包括TCP/IP。这个问题第5个回答发送的过程是发送到缓冲区和从缓冲区发送到网络上WSAEWOULDBLOCK和粘包都是出现在发送到缓冲区这个过程的Socket编程 (异步通讯,解决Tcp粘包)前面提到TCP会出现粘包问题下面将以实例演示解决方案问题一般会出现的情况如下,假设我们连续发送两条两天记录(我是liger_zql)模拟发送示例 #region 测试消息发送,并匹配协议 TcpClient client new TcpClient(); client.AsynConnect(); Console.WriteLine(下面将连续发送2条测试消息...); Console.ReadKey(); MessageProtocol msgPro; for (int i 0; i2; i) { msgPro newMessageProtocol(我是liger_zql); Console.WriteLine(第{0}条{1}, i 1,msgPro.MessageInfo.Content); client.AsynSend(msgPro); } #endregion 接收端接受两条信息会出现如下三种情况1.(1)我是liger_zql(2)我是liger_zql2.(1)我是liger_zql我是(2)liger_zql3.(1)我是liger_zql我是liger_zql通过以上三种情况显然2、3都不是我们想要的结果。那么如何处理这中情况呢 解决方案通过自定义协议...我们可以以将信息以xml的格式发送出去列入protocolcontent/protocol通过正则匹配信息是否完整如果不完整我们可以先将本次接受信息缓存接受下一次信息再次匹配得到相应的结果。1将信息对象转换成一定格式的xml字符串2对接收的信息通过正则进行匹配处理3将该定义的协议换换成信息对象通过对象获取自己想要的信息。结果最后运行结果如下 附上源码SocketProQuests.zip详细可参考http://www.cnblogs.com/zengqinglei/archive/2013/05/14/3078842.html 附关于Socket/TCP粘包、多包和少包, 断包http://tsing01.blog.163.com/blog/static/2059572832012716103711125/ 关于Tcp封包粘包问题http://www.cnblogs.com/jiangtong/archive/2012/03/22/2411985.htmlTCP通讯处理粘包详解http://www.cnblogs.com/smark/p/3284756.html