- 浏览: 137030 次
- 性别:
- 来自: 郑州
文章分类
最新评论
-
Ken艹小哲:
太赞了 哥们 加扣
猜数字问题的最少步数算法. -
chenyuan122912:
...
解决AS3 Socket编程中最令人头疼的问题 -
hyx0914:
有源代码打包下载的吗?
Flex地图分块加载的实现 -
tianhai110:
非常有价值的 测试总结
时间效率,Timer和EnterFrame在FP 10.1之后测试和建议 -
763675117:
你好,fengxiangpiao,看了你的文档,我的需求和你差 ...
解决MovieClip打印问题 转
这些天做类似QQ空间的斗地主,被网络沾包的问题搞死了,所以查资料了解记录一下:
一两个简单概念长连接与短连接:
1.长连接
Client方与Server方先建立通讯连接,连接建立后不断开, 然后再进行报文发送和接收。
2.短连接
Client方与Server每进行一次报文收发交易时才进行通讯连接,交易完毕后立即断开连接。此种方式常用于一点对多点
通讯,比如多个Client连接一个Server.
二 什么时候需要考虑粘包问题?
1:如果利用tcp每次发送数据,就与对方建立连接,然后双方发送完一段数据后,就关闭连接,这样就不会出现粘包问题(因为只有一种包结构,类似于 http协议)。关闭连接主要要双方都发送close连接(参考tcp关闭协议)。如:A需要发送一段字符串给B,那么A与B建立连接,然后发送双方都默认好的协议字符如"hello give me sth abour yourself",然后B收到报文后,就将缓冲区数据接收,然后关闭连接,这样粘包问题不用考虑到,因为大家都知道是发送一段字符。
2:如果发送数据无结构,如文件传输,这样发送方只管发送,接收方只管接收存储就ok,也不用考虑粘包
3:如果双方建立连接,需要在连接后一段时间内发送不同结构数据,如连接后,有好几种结构:
1)"hello give me sth abour yourself"
2)"Don't give me sth abour yourself"
那这样的话,如果发送方连续发送这个两个包出去,接收方一次接收可能会是"hello give me sth abour yourselfDon't give me sth abour yourself" 这样接收方就傻了,到底是要干嘛?不知道,因为协议没有规定这么诡异的字符串,所以要处理把它分包,怎么分也需要双方组织一个比较好的包结构,所以一般可能会在头加一个数据长度之类的包,以确保接收。
三 粘包出现原因:在流传输中出现,UDP不会出现粘包,因为它有消息边界(参考Windows 网络编程)
1 发送端需要等缓冲区满才发送出去,造成粘包
2 接收方不及时接收缓冲区的包,造成多个包接收
解决办法:
为了避免粘包现象,可采取以下几种措施。一是对于发送方引起的粘包现象,用户可通过编程设置来避免,TCP提供了强制数据立即传送的操作指令push,TCP软件收到该操作指令后,就立即将本段数据发送出去,而不必等待发送缓冲区满;二是对于接收方引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象;三是由接收方控制,将一包数据按结构字段,人为控制分多次接收,然后合并,通过这种手段来避免粘包。
以上提到的三种措施,都有其不足之处。第一种编程设置方法虽然可以避免发送方引起的粘包,但它关闭了优化算法,降低了网络发送效率,影响应用程序的性能,一般不建议使用。第二种方法只能减少出现粘包的可能性,但并不能完全避免粘包,当发送频率较高时,或由于网络突发可能使某个时间段数据包到达接收方较快,接收方还是有可能来不及接收,从而导致粘包。第三种方法虽然避免了粘包,但应用程序的效率较低,对实时应用的场合不适合。
相关文章截取:
一个包没有固定长度,以太网限制在46-1500字节,1500就是以太网的MTU,超过这个量,TCP会为IP数据报设置偏移量进行分片传输,现在一般可允许应用层设置8k(NTFS系)的缓冲区,8k的数据由底层分片,而应用看来只是一次发送。windows的缓冲区经验值是4k,Socket 本身分为两种,流(TCP)和数据报(UDP),你的问题针对这两种不同使用而结论不一
样。甚至还和你是用阻塞、还是非阻塞Socket来编程有关。
1、通信长度,这个是你自己决定的,没有系统强迫你要发多大的包,实际应该根据需求和网络状况来决定。对于TCP,这个长度可以大点,但要知道,Socket内部默认的收发缓冲区大小大概是8K,你可以用SetSockOpt来改变。但对于UDP,就不要太大,一般在1024至10K。注意一点,你无论发多大的包,IP层和链路层都会把你的包进行分片发送,一般局域网就是1500左右,广域网就只有几十字节。分片后的包将经过不同的路由到达接收方,对于UDP而言,要是其中一个分片丢失,那么接收方的IP层将把整个发送包丢弃,这就形成丢包。显然,要是一个UDP发包佷大,它被分片后,链路层丢失分片的几率就佷大,你这个UDP包,就佷容易丢失,但是太小又影响效率。最好可以配置这个值,以根据不同的环境来调整到最佳状态。
send()函数返回了实际发送的长度,在网络不断的情况下,它绝不会返回(发送失败的)错误,最多就是返回0。对于TCP你可以字节写一个循环发送。当send函数返回SOCKET_ERROR时,才标志着有错误。但对于UDP,你不要写循环发送,否则将给你的接收带来极大的麻烦。所以UDP需要用SetSockOpt来改变Socket内部Buffer的大小,以能容纳你的发包。明确一点,TCP作为流,发包是不会整包到达的,而是源源不断的到,那接收方就必须组包。而UDP作为消息或数据报,它一定是整包到达接收方。
2、关于接收,一般的发包都有包边界,首要的就是你这个包的长度要让接收方知道,于是就有个包头信息,对于TCP,接收方先收这个包头信息,然后再收包数据。一次收齐整个包也可以,可要对结果是否收齐进行验证。这也就完成了组包过程。UDP,那你只能整包接收了。要是你提供的接收Buffer过小,TCP将返回实际接收的长度,余下的还可以收,而UDP不同的是,余下的数据被丢弃并返回WSAEMSGSIZE错误。注意TCP,要是你提供的 Buffer佷大,那么可能收到的就是多个发包,你必须分离它们,还有就是当Buffer太小,而一次收不完Socket内部的数据,那么Socket接收事件(OnReceive),可能不会再触发,使用事件方式进行接收时,密切注意这点。这些特性就是体现了流和数据包的区别。
相关参考文章:
http://www.cnblogs.com/alon/archive/2009/04/16/1437600.html
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/binghuazh/archive/2009/05/28/4222516.aspx
解决TCP网络传输“粘包”问题
当前在网络传输应用中,广泛采用的是TCP/IP通信协议及其标准的socket应用开发编程接口(API)。TCP/IP传输层有两个并列的协议:TCP和UDP。其中TCP(transport control protocol,传输控制协议)是面向连接的,提供高可靠性服务。UDP(user datagram protocol,用户数据报协议)是无连接的,提供高效率服务。在实际工程应用中,对可靠性和效率的选择取决于应用的环境和需求。一般情况下,普通数据的网络传输采用高效率的udp,重要数据的网络传输采用高可靠性的TCP。
在应用开发过程中,笔者发现基于TCP网络传输的应用程序有时会出现粘包现象(即发送方发送的若干包数据到接收方接收时粘成一包)。针对这种情况,我们进行了专题研究与实验。本文重点分析了TCP网络粘包问题,并结合实验结果提出了解决该问题的对策和方法,供有关工程技术人员参考。
一、TCP协议简介
TCP是一个面向连接的传输层协议,虽然TCP不属于iso制定的协议集,但由于其在商业界和工业界的成功应用,它已成为事实上的网络标准,广泛应用于各种网络主机间的通信。
作为一个面向连接的传输层协议,TCP的目标是为用户提供可靠的端到端连接,保证信息有序无误的传输。它除了提供基本的数据传输功能外,还为保证可靠性采用了数据编号、校验和计算、数据确认等一系列措施。它对传送的每个数据字节都进行编号,并请求接收方回传确认信息(ack)。发送方如果在规定的时间内没有收到数据确认,就重传该数据。数据编号使接收方能够处理数据的失序和重复问题。数据误码问题通过在每个传输的数据段中增加校验和予以解决,接收方在接收到数据后检查校验和,若校验和有误,则丢弃该有误码的数据段,并要求发送方重传。流量控制也是保证可靠性的一个重要措施,若无流控,可能会因接收缓冲区溢出而丢失大量数据,导致许多重传,造成网络拥塞恶性循环。TCP采用可变窗口进行流量控制,由接收方控制发送方发送的数据量。
TCP为用户提供了高可靠性的网络传输服务,但可靠性保障措施也影响了传输效率。因此,在实际工程应用中,只有关键数据的传输才采用TCP,而普通数据的传输一般采用高效率的udp。
二、粘包问题分析与对策
TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。
出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据(图1所示)。
图1
图2
图3
粘包情况有两种,一种是粘在一起的包都是完整的数据包(图1、图2所示),另一种情况是粘在一起的包有不完整的包(图3所示),此处假设用户接收缓冲区长度为m个字节。
不是所有的粘包现象都需要处理,若传输的数据为不带结构的连续流数据(如文件传输),则不必把粘连的包分开(简称分包)。但在实际工程应用中,传输的数据一般为带结构的数据,这时就需要做分包处理。
在处理定长结构数据的粘包问题时,分包算法比较简单;在处理不定长结构数据的粘包问题时,分包算法就比较复杂。特别是如图3所示的粘包情况,由于一包数据内容被分在了两个连续的接收包中,处理起来难度较大。实际工程应用中应尽量避免出现粘包现象。
为了避免粘包现象,可采取以下几种措施。一是对于发送方引起的粘包现象,用户可通过编程设置来避免,TCP提供了强制数据立即传送的操作指令 push,TCP软件收到该操作指令后,就立即将本段数据发送出去,而不必等待发送缓冲区满;二是对于接收方引起的粘包,则可通过优化程序设计、精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据,从而尽量避免出现粘包现象;三是由接收方控制,将一包数据按结构字段,人为控制分多次接收,然后合并,通过这种手段来避免粘包。
以上提到的三种措施,都有其不足之处。第一种编程设置方法虽然可以避免发送方引起的粘包,但它关闭了优化算法,降低了网络发送效率,影响应用程序的性能,一般不建议使用。第二种方法只能减少出现粘包的可能性,但并不能完全避免粘包,当发送频率较高时,或由于网络突发可能使某个时间段数据包到达接收方较快,接收方还是有可能来不及接收,从而导致粘包。第三种方法虽然避免了粘包,但应用程序的效率较低,对实时应用的场合不适合。
一种比较周全的对策是:接收方创建一预处理线程,对接收到的数据包进行预处理,将粘连的包分开。对这种方法我们进行了实验,证明是高效可行的。
三、编程与实现
1.实现框架
实验网络通信程序采用TCP/IP协议的socket api编程实现。socket是面向客户机/服务器模型的。TCP实现框架如图4所示。
图4
2.实验硬件环境:
服务器:pentium 350 微机
客户机:pentium 166微机
网络平台:由10兆共享式hub连接而成的局域网
3.实验软件环境:
操作系统:windows 98
编程语言:visual c++ 5.0
4.主要线程
编程采用多线程方式,服务器端共有两个线程:发送数据线程、发送统计显示线程。客户端共有三个线程:接收数据线程、接收预处理粘包线程、接收统计显示线程。其中,发送和接收线程优先级设为thread_priority_time_critical(最高优先级),预处理线程优先级为 thread_priority_above_normal(高于普通优先级),显示线程优先级为thread_priority_normal(普通优先级)。
实验发送数据的数据结构如图5所示:
图5
5.分包算法
针对三种不同的粘包现象,分包算法分别采取了相应的解决办法。其基本思路是首先将待处理的接收数据流(长度设为m)强行转换成预定的结构数据形式,并从中取出结构数据长度字段,即图5中的n,而后根据n计算得到第一包数据长度。
1)若n<m,则表明数据流包含多包数据,从其头部截取n个字节存入临时缓冲区,剩余部分数据依此继续循环处理,直至结束。
2)若n=m,则表明数据流内容恰好是一完整结构数据,直接将其存入临时缓冲区即可。
3)若n>m,则表明数据流内容尚不够构成一完整结构数据,需留待与下一包数据合并后再行处理。
对分包算法具体内容及软件实现有兴趣者,可与作者联系。
四、实验结果分析
实验结果如下:
1.在上述实验环境下,当发送方连续发送的若干包数据长度之和小于1500b时,常会出现粘包现象,接收方经预处理线程处理后能正确解开粘在一起的包。若程序中设置了“发送不延迟”:(setsockopt (socket_name,ipproto_tcp,tcp_nodelay,(char *) &on,sizeof on) ,其中on=1),则不存在粘包现象。
2.当发送数据为每包1kb~2kb的不定长数据时,若发送间隔时间小于10ms,偶尔会出现粘包,接收方经预处理线程处理后能正确解开粘在一起的包。
3.为测定处理粘包的时间,发送方依次循环发送长度为1.5kb、1.9kb、1.2kb、1.6kb、1.0kb数据,共计1000包。为制造粘包现象,接收线程每次接收前都等待10ms,接收缓冲区设为5000b,结果接收方收到526包数据,其中长度为5000b的有175包。经预处理线程处理可得到1000包正确数据,粘包处理总时间小于1ms。
实验结果表明,TCP粘包现象确实存在,但可通过接收方的预处理予以解决,而且处理时间非常短(实验中1000包数据总共处理时间不到 1ms),几乎不影响应用程序的正常工作。
发表评论
-
最全的Flex网站
2011-10-15 23:18 722一、国外站点 1.资源 类Adobe Flex 2 ... -
时间效率,Timer和EnterFrame在FP 10.1之后测试和建议
2011-04-23 22:19 1056关于Timer还是EnterFrame的选择,一直是很 ... -
时间效率,Timer 和 EnterFrame 在 FP 10.1 之后测试和建议
2011-04-23 22:16 1058关于Timer还是EnterFrame的选择,一直是很多AS3 ... -
关于Flash Socket通信的安全策略问题的一点心得
2011-04-22 22:36 697昨天做测试的时候遇到 ... -
FLEX入门实例--------FLEX全屏功能实现及右键菜单
2011-03-26 11:58 815FLEX的全屏功能的实现,光写AS还不够,还需要对JS部分做一 ... -
flex中的Text属性
2010-12-08 12:31 870不同于Lable只显示单行文本,Text可以显示多行文本, ... -
Flex跨域问题
2010-11-08 17:55 789From ESRI: The client brow ... -
Flex屏蔽并自定义鼠标右键菜单(转载)
2010-11-08 17:53 877最近手头有个项目需要屏蔽Flex鼠标右键菜单并自定义新的fle ... -
使用 IBM Rational Functional Tester 7.0.1 测试 Flex 应用程序
2010-11-05 21:45 838关于这篇文章必要的信息 这篇文章假定您已经对使用 IBM® ... -
在 Ajax 应用程序中实现实时数据推送
2010-11-05 21:40 666简介 Ajax 技术已经存在了一段时间,开发的动力已经真正开 ... -
使用 Flex 和 Dojo 开发交互式Web应用程序
2010-11-05 21:38 987引言 以用户体验为核 ... -
Flex 应用内存泄露的分析与诊断
2010-11-05 21:36 801引言 Flex 采用 ActionScrip ... -
flex SystemManger
2010-11-05 16:35 689软件编程牛人网 Framework Fundamentals ... -
Flex 不同 application 之间传参数
2010-11-05 16:33 485软件编程牛人网 通过主影片来获得所有子影片的systemma ... -
如何在flash保留小数位
2010-11-04 20:07 822在家上网赚钱更容易 fl ... -
实例讲解Flex3的SharedObject对象用法
2010-11-04 16:01 756在家上网赚钱更容易 Flex中的SharedObj ... -
Flex中12个最基本、最简单但却最有用的函数
2010-11-04 15:54 689在家上网赚钱更容易 No.1 复制内容到剪贴板 S ... -
谈谈Flex中ArrayCollection的复制(克隆)
2010-11-04 15:51 717在家上网赚钱更容易 在Flex的开发过程中,常常会遇到复 ... -
flex中的拖放操作(一)
2010-11-04 15:47 929在家上网赚钱更容易 可视化的开发环境最大的特点是允许你在 ... -
flex中的拖放操作(二)
2010-11-04 15:46 768在家上网赚钱更容易 手动添加 drag-and-drop ...
相关推荐
Socket 粘包问题的 3 种解决方案,最后一种最完美 在本文中,我们将讨论 Socket 粘包问题的 3 种解决方案,并详细解释每种解决方案的优缺点。最后,我们将介绍一种完美的解决方案,帮助开发者更好地解决 Socket ...
C#解决socket通信过程中粘包分包问题,本项目是一个只有6...在消息正文的前方加入一个固定长度的数字表示消息正文的长度,这样就可以基本解决分包和粘包问题。整个工程基本基于良好的面向对象思想,代码注释清晰简洁。
Socket 粘包问题终极解决方案-Netty 版 Socket 粘包问题是指在使用 TCP 协议进行网络通讯时,由于 TCP 协议本身没有边界的概念,导致在传输数据时无法确定消息的边界,从而产生粘包和半包问题。本文将详细介绍 ...
"TCP\Socket粘包处理(加长度头)"这个主题主要涉及如何解决这个问题。在TCP中处理粘包的关键是添加一种机制来区分不同的数据包。一种常见的方法是在每个数据包前添加一个“长度头”,这个长度头包含了接下来的数据包...
本文将详细介绍如何使用GOLANG来解决SOCKET通信中的粘包问题。 首先,理解粘包产生的原因。TCP协议是基于流的,没有明确的数据边界。它会根据网络状况和缓冲区大小来决定何时发送数据,这就可能导致连续发送的...
在Golang中,处理TCP Socket粘包问题通常涉及以下几个方面: 1. **消息边界**:为了区分不同的消息,我们需要在数据中加入消息边界。例如,可以在每个消息前加上一个固定长度的消息头,头里面包含消息的总长度。...
类型字段标识数据包的类型,长度字段记录了值字段的大小,这样接收端可以根据长度字段来确定每个数据包的结束位置,有效避免了粘包问题。例如,在网络游戏服务器架构中,不同的消息可能对应不同的类型,如登录请求、...
本样例可以实现Socket、串口通讯的接收数据的分析和处理,支持各种复杂粘包的数据处理。 样例中用到的协议是特定的协议,您只需根据自己的协议格式修改其中的指令长度判定方法、指令长度占用字节数等方面,就能很...
C# Socket粘包处理是指在使用Socket编程时,如何解决粘包问题的技术。粘包问题是指当多个消息发送给服务器时,服务器可能会将多个消息合并成一个包发送给客户端,从而导致客户端无法正确地接收和处理消息。 在C#中...
### Socket编程TCP粘包问题及解决方案 #### 一、TCP粘包问题概述 TCP作为一种可靠的面向连接的传输层协议,提供了基于字节流的服务。在TCP传输过程中,发送方发送的数据被视为连续不断的字节流,而不是离散的消息...
本篇文章将深入探讨如何在使用SuperSocket.ClientEngine.Core库时,处理客户端的粘包和半包问题。 粘包和半包是网络通信中的常见问题,主要出现在TCP协议中。由于TCP为了提高传输效率,会将多个小的数据包合并成一...
当前在网络传输应用中,广泛采用的是TCP/IP通信协议及其标准的socket应用开发编程接口(API)。TCP/IP传输层有两个并列的协议:TCP和UDP。其中TCP(transport control protocol,传输控制协议)是面向连接的,提供高...
在TCP/IP通信中,"粘包"问题是一个常见的现象,...总的来说,处理TCP粘包问题需要理解TCP的工作原理,并结合适当的策略来确保数据的正确传输和处理。在实际应用中,通常需要结合具体需求和场景来选择最合适的解决方案。
本项目"Unity + Socket + Protobuff+异步+粘包拆包断包_V2"聚焦于解决在使用Socket进行网络通信时常见的问题,如粘包、拆包、断包以及断线重连等,同时结合了Protocol Buffers(Protobuff)这一高效的数据序列化协议...
本文将深入探讨如何使用C#语言来实现Socket编程,特别是在处理异步通信和解决TCP粘包问题的第三阶段。C#提供了丰富的类库支持网络编程,使得开发者能够方便地构建基于TCP/IP的客户端和服务器应用。 首先,让我们...
Socket通信是计算机网络编程中的重要组成部分,主要用于实现进程间的通信,尤其在分布式系统和...通过深入学习和理解这个文件,我们可以更好地掌握Socket通信中如何解决粘包问题,从而编写出高效、健壮的网络程序。
第八周-第07章节-Python3.5-Socket粘包.avi
第八周-第08章节-Python3.5-Socket粘包深入编码.avi
本教程将深入探讨如何在Unity中实现Socket通信,包括TCP连接、粘包/拆包问题的解决方案。 一、TCP连接基础 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在Unity中...