TCP Socket 粘包
这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题。发现自己不是非常清楚,所以查资料了解记录一下:
一两个简单概念长连接与短连接:
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包。就佷easy丢失,可是太小又影响效率。最好能够配置这个值,以依据不同的环境来调整到最佳状态。
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
TCP Socket 粘包的更多相关文章
- golang中tcp socket粘包问题和处理
转自:http://www.01happy.com/golang-tcp-socket-adhere/ 在用golang开发人工客服系统的时候碰到了粘包问题,那么什么是粘包呢?例如我们和客户端约定数据 ...
- C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性
C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性 上节我们讲到了socket缓冲区和数据的传递过程,可以看到数据的接收和发送是无关的,read()/recv() 函数不管数据发 ...
- Socket粘包问题
这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...
- TCP拆包粘包之分隔符解码器
TCP以流的方式进行数据传输,上层的应用协议为了对消息进行区分,往往采用如下4种方式. (1)消息长度固定,累计读取到长度总和为定长LEN的报文后,就认为读取到了一个完整的消息:将计数器置位,重新开始 ...
- [转]关于Socket粘包问题
这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...
- python 网络编程之TCP传输&粘包传输
只有TCP有粘包现象,UDP永远不会粘包. 所谓粘包问题主要还是C/S两端数据传输时 因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的 根本原因:粘包是由TCP协议本身造成的,T ...
- python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)
一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...
- TCP通信粘包问题分析和解决
转载至https://www.cnblogs.com/kex1n/p/6502002.html 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发 ...
- TCP通信粘包问题分析和解决(全)(转)
TCP通信粘包问题分析和解决(全) 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送 ...
随机推荐
- Linux 操作当前时间
一.查看和修改Linux的时区 1. 查看当前时区 命令 : "date -R" 2. 修改设置Linux服务器时区 方法 A 命令 : "tzselect" ...
- springboot 启动类CommandLineRunner(转载)
在Spring boot项目的实际开发中,我们有时需要项目服务启动时加载一些数据或预先完成某些动作.为了解决这样的问题,Spring boot 为我们提供了一个方法:通过实现接口 CommandLin ...
- 终端控制类getopt isatty select ttyname
getopt(分析命令行参数) 相关函数 表头文件 #include<unistd.h> 定义函数 int getopt(int argc,char * const argv[ ],con ...
- PHP自己定义安装
① 自己定义安装(先要在管理里停止apache服务,再卸载apache.再安装时不须要重新启动电脑) apache+php+mysql+phpmyadmin自行安装 我们建议大家,安装的时候安装到同一 ...
- Windows 7系统垃圾清理自写程序
系统清理.bat @echo off color 0a title windows7系统垃圾清理--- echo ★☆ ★☆ ★☆ ★☆ ★☆★☆★☆ ★☆ ★☆ ★☆ ★☆★ echo ★☆ ★☆ ...
- [15] 星星(Star)图形的生成算法
顶点数据的生成 bool YfBuildStarVertices ( Yreal radius, Yreal assistRadius, Yreal height, Yuint slices, YeO ...
- Informatica 常用组件Source Qualifier之七 输入过滤器
通过输入源过滤器,可以降低 PowerCenter 查询的行数.如果在源过滤器中包括字符串 "WHERE" 或较大对象,PowerCenter 将使会话失败. 源限定符转换包括默 ...
- Length of Last Word leetocde java
题目: Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return t ...
- App优化 Systrace
简介 trace [tres] vt.跟踪,追踪; 追溯,探索; 探索; 查找; n.痕迹; 痕迹,踪迹; 微量,极少量; 1 1 1 trace [tres] vt.跟踪,追踪; 追溯,探索; ...
- (回溯法)和为n的所有不增正整数和式分解算法
题目: 利用递归算法输出正整数和为n的所有不增的正整数和式.例如当n=5时,不增的和式如下: 5=5 5=4+1 5=3+2 5=3+1+1 5=2+2+1 5=2+1+1+1 5=1+1+1+1+1 ...