首先看两个概念: 
短连接:  
连接->传输数据->关闭连接 
   HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。 
   也可以这样说:短连接是指SOCKET连接后发送后接收完数据后马上断开连接。

长连接:  
连接->传输数据->保持连接 -> 传输数据-> 。。。 ->关闭连接。 
长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。

之所以出现粘包和半包现象,是因为TCP当中,只有流的概念,没有包的概念.

半包  
指接受方没有接受到一个完整的包,只接受了部分,这种情况主要是由于TCP为提高传输效率,将一个包分配的足够大,导致接受方并不能一次接受完。 (在长连接和短连接中都会出现)。

粘包与分包  
指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。出现粘包现象的原因是多方面的,它既可能由发送方造成,也可能由接收方造成。发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。这是因为接收方先把收到的数据放在系统接收缓冲区,用户进程从该缓冲区取数据,若下一包数据到达时前一包数据尚未被用户进程取走,则下一包数据放到系统接收缓冲区时就接到前一包数据之后,而用户进程根据预先设定的缓冲区大小从系统接收缓冲区取数据,这样就一次取到了多包数据。分包是指在出现粘包的时候我们的接收方要进行分包处理。 (在长连接中都会出现)

什么时候需要考虑半包的情况?  
从备注中我们了解到Socket内部默认的收发缓冲区大小大概是8K,但是我们在实际中往往需要考虑效率问题,重新配置了这个值,来达到系统的最佳状态。 
一个实际中的例子:用mina作为服务器端,使用的缓存大小为10k,这里使用的是短连接,所有不用考虑粘包的问题。 
问题描述:在并发量比较大的情况下,就会出现一次接受并不能完整的获取所有的数据。 
处理方式: 
1.通过包头+包长+包体的协议形式,当服务器端获取到指定的包长时才说明获取完整。 
2.指定包的结束标识,这样当我们获取到指定的标识时,说明包获取完整。

什么时候需要考虑粘包的情况?  
1.当时短连接的情况下,不用考虑粘包的情况 
2.如果发送数据无结构,如文件传输,这样发送方只管发送,接收方只管接收存储就ok,也不用考虑粘包 
3.如果双方建立连接,需要在连接后一段时间内发送不同结构数据 
处理方式: 
接收方创建一预处理线程,对接收到的数据包进行预处理,将粘连的包分开 
注:粘包情况有两种,一种是粘在一起的包都是完整的数据包,另一种情况是粘在一起的包有不完整的包

备注: 
一个包没有固定长度,以太网限制在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),可能不会再触发,使用事件方式进行接收时,密切注意这点。这些特性就是体现了流和数据包的区别。

socket的半包,粘包与分包的问题相关推荐

  1. 自定义Udp/Tcp协议,通信协议Socket/WebSocket,IM粘包、分包解决等(2),ProtocolBuffer

    > 自定义Udp/Tcp协议/通信协议(Java/C):自定义构建和解析IM协议消息:IM自定义UDP通信协议   类似于网络通信中的TCPIP协议一般,比较可靠的通信协议往往包含有以下几个组成 ...

  2. java socket分包粘包 代码_分享java中处理socket通信过程中粘包情况的实例代码

    本篇文章主要介绍了java中处理socket通信过程中粘包的情况,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 这两天学习了java中处理socket通信过程中粘包的情况,而且很重要,所以,今天添 ...

  3. java nio解决半包 粘包问题

    java nio解决半包 粘包问题 NIO socket是非阻塞的通讯模式,与IO阻塞式的通讯不同点在于NIO的数据要通过channel放到一个缓存池ByteBuffer中,然后再从这个缓存池中读出数 ...

  4. netty 客户端断开 异常处理_netty案例,netty4.1基础入门篇八《NettyClient半包粘包处理》发数据方式》...

    小傅哥 | https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获.专注于原创专题案例编写,目前已完成的专题有:Netty4.x实战专题案例.用Java实现JVM.基于Ja ...

  5. 使用包定长FixedLengthFrameDecoder解决半包粘包

    四.使用包定长FixedLengthFrameDecoder解决半包粘包 4.1 试验 由于客户端发给服务器端的是hello server,im a client字符串,该字符串占用24字节,所以在服 ...

  6. Socket TCP协议解决粘包、半包问题的三种解决方案

    什么是粘包.半包问题:         粘包:例如服务端依次将两条消息发送给客户端,我们暂且简单的将这两条消息举例为"Hello"."Unity",而客户端一次 ...

  7. netty半包粘包 处理_老王:Netty到底是个什么鬼?有没有简单的理解方式?

    前语:不要为了读文章而读文章,一定要带着问题来读文章,勤思考. 作者:lyowish    来源:http://1t.click/7RY # 从HTTP说起 有了Netty,你可以实现自己的HTTP服 ...

  8. http之 半包 粘包

    短连接:  连接->传输数据->关闭连接     HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接.     也可以这样说:短连接是指SOCK ...

  9. netty半包粘包 处理_Java NIO 框架 Netty 之美:粘包与半包问题

    一.前言 Netty 是一个可以快速开发网络应用程序的 NIO 框架,它大大简化了 TCP 或者 UDP 服务器的网络编程.Netty 的简易和快速开发并不意味着由它开发的程序将失去可维护性或者存在性 ...

  10. linux下socket编程处理TCP粘包

    一. 数据接收时会出现以下几种情况 一次接收到了客户端发送过来的一个完整的数据包 一次接收到了客户端发送过来的 N 个数据包,由于每个包的长度不定,无法将各个数据包拆开 一次接收到了一个或者 N 个数 ...

最新文章

  1. helloworld 1 2結合版 (有意思)
  2. python选择表单_如何使用Python在表单中选择选项?
  3. nodejs websocket server
  4. 夸奖对方代码写的好_测一测,你写的代码性能好吗?
  5. 关于前端样式定位的一些自己的看法
  6. java基础 super 子类调用父类
  7. Critical dependency: require function dependencies cannot be statically extracted
  8. 最新Spring下载网址
  9. 26 伪造ICMP数据包
  10. 直播纠纷处理指引已出台,电商直播严监管来了!
  11. pandas中关于nan的处理
  12. 为什么AI公司都在一边融资,一边投资? | 甲子光年
  13. 体外诊断(POCT)之检测卡配置文件
  14. vlc命令行: 转码 流化 推流
  15. 索爱SE8头戴蓝牙耳机,带上它外面的世界与我无关
  16. Java调用arcgis导入shape,java for arcgis 之——将shapefile导入SDE
  17. python批量保存网页内容到PDF
  18. Ubuntu平台 常用插件下载(部分含源码)
  19. MySQL mdl导入_MySQL · 特性分析 · MDL 实现分析
  20. 怎么在电脑上玩风之大陆 风之大陆电脑版玩法教程

热门文章

  1. Windows7自动安装驱动功能关闭与开启教程
  2. vuex 基本入门和使用(二)
  3. saltstack中salt-key收集的主机名与实际主机名不一致
  4. Oracle的逻辑结构(表空间、段、区间、块)——Oracle数据块(一)
  5. 前端测试简述及使用Karma/Mocha实现的集成测试栗子(Travis CI/Coverage)
  6. Spring配置问题——元素 quot;context:component-scanquot; 的前缀 quot;contextquot; 未绑定...
  7. word文档快速取消图片的链接
  8. JAVA时间日期处理类,主要用来遍历两个日期之间的每一天。
  9. 基于角色的权限设计(一)
  10. 第 4 章 Glance - 022 - 如何使用 OpenStack CLI