这两天看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 粘包的更多相关文章

  1. golang中tcp socket粘包问题和处理

    转自:http://www.01happy.com/golang-tcp-socket-adhere/ 在用golang开发人工客服系统的时候碰到了粘包问题,那么什么是粘包呢?例如我们和客户端约定数据 ...

  2. C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性

    C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性 上节我们讲到了socket缓冲区和数据的传递过程,可以看到数据的接收和发送是无关的,read()/recv() 函数不管数据发 ...

  3. Socket粘包问题

    这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...

  4. TCP拆包粘包之分隔符解码器

    TCP以流的方式进行数据传输,上层的应用协议为了对消息进行区分,往往采用如下4种方式. (1)消息长度固定,累计读取到长度总和为定长LEN的报文后,就认为读取到了一个完整的消息:将计数器置位,重新开始 ...

  5. [转]关于Socket粘包问题

    这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下: 一两个简单概念长连接与短连接:1.长连接 Client方与Server方先建立通 ...

  6. python 网络编程之TCP传输&粘包传输

    只有TCP有粘包现象,UDP永远不会粘包. 所谓粘包问题主要还是C/S两端数据传输时 因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的 根本原因:粘包是由TCP协议本身造成的,T ...

  7. python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)

    一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...

  8. TCP通信粘包问题分析和解决

    转载至https://www.cnblogs.com/kex1n/p/6502002.html 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发 ...

  9. TCP通信粘包问题分析和解决(全)(转)

    TCP通信粘包问题分析和解决(全) 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送 ...

随机推荐

  1. Linux 操作当前时间

    一.查看和修改Linux的时区 1. 查看当前时区 命令 : "date -R" 2. 修改设置Linux服务器时区 方法 A 命令 : "tzselect" ...

  2. springboot 启动类CommandLineRunner(转载)

    在Spring boot项目的实际开发中,我们有时需要项目服务启动时加载一些数据或预先完成某些动作.为了解决这样的问题,Spring boot 为我们提供了一个方法:通过实现接口 CommandLin ...

  3. 终端控制类getopt isatty select ttyname

    getopt(分析命令行参数) 相关函数 表头文件 #include<unistd.h> 定义函数 int getopt(int argc,char * const argv[ ],con ...

  4. PHP自己定义安装

    ① 自己定义安装(先要在管理里停止apache服务,再卸载apache.再安装时不须要重新启动电脑) apache+php+mysql+phpmyadmin自行安装 我们建议大家,安装的时候安装到同一 ...

  5. Windows 7系统垃圾清理自写程序

    系统清理.bat @echo off color 0a title windows7系统垃圾清理--- echo ★☆ ★☆ ★☆ ★☆ ★☆★☆★☆ ★☆ ★☆ ★☆ ★☆★ echo ★☆ ★☆ ...

  6. [15] 星星(Star)图形的生成算法

    顶点数据的生成 bool YfBuildStarVertices ( Yreal radius, Yreal assistRadius, Yreal height, Yuint slices, YeO ...

  7. Informatica 常用组件Source Qualifier之七 输入过滤器

    通过输入源过滤器,可以降低 PowerCenter  查询的行数.如果在源过滤器中包括字符串 "WHERE" 或较大对象,PowerCenter 将使会话失败. 源限定符转换包括默 ...

  8. Length of Last Word leetocde java

    题目: Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return t ...

  9. App优化 Systrace

    简介 trace [tres] vt.跟踪,追踪; 追溯,探索; 探索; 查找; n.痕迹; 痕迹,踪迹; 微量,极少量; 1 1   1 trace [tres] vt.跟踪,追踪; 追溯,探索; ...

  10. (回溯法)和为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 ...