C# TCP socket发送大数据包时,接收端和发送端数据不一致 服务端接收Receive不完全
C# TCP socket发送大数据包时,接收端和发送端数据不一致 服务端接收Receive不完全
在发送端,一次发送200k个字节,在接收端,一次接收200k个字节,
但是在接收端,经常会出现 socket.receive 接收不全的情况 ,
偶尔接收的包也是正常的,用Wireshark抓包发现,每次发送都分成了多个1514字节长的数据包,一次数据有多个数据包,

标准以太网帧长度下限为:64 字节
标准以太网帧长度上限为:1518 字节
每个数据包含1448字节有效数据

这也正好解释了为什么接收数据包不完整时接收到的长度都正好是1448的倍数如1448,2896,4344等等
所以需要多次接收然后对数据进行合并,代码如下:
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.ReceiveBufferSize = * * ;
listener.ReceiveTimeout = ;
listener.Bind(localEndPoint); Socket sock = listener.Accept();
byte[] bs = new byte[*];
int ilen = sock.Receive(bs);
uint length = ByteTouint(bs, , );
while (ilen < length)
{
int ii = sock.Receive(bs, ilen, * , SocketFlags.None);
ilen = ilen + ii;
}
这样接收的内容就对了。
异步方式里 C# 的TCP Socket (异步方式) ,在ReadCallback里
while (bytesRead < state.bodybuffer.Length)
{
int ii = handler.Receive(state.bodybuffer, bytesRead, state.bodybuffer.Length - bytesRead, SocketFlags.None);
bytesRead = bytesRead + ii;
}
链接:https://www.zhihu.com/question/21524257/answer/118266374
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
最早的以太网工作方式:载波多路复用/冲突检测CSMA/CD,因为网络是共享的,即任何一个节点发送数据之前,先要侦听线路上是否有数据在传输,如果有,需要等待,如果线路可用,才可以发送。
假设A发出第一个bit位,到达B,而B也正在传输第一个bit位,于是产生冲突,冲突信号得让A在完成最后一个bit位之前到达A,这个一来一回的时间间隙slot time是57.6μs.
在10Mbps的网络中,在57.6μs的时间内,能够传输576个bit,所以要求以太网帧最小长度为576个bits,从而让最极端的碰撞都能够被检测到。这个576bit换算一下就是72个字节,去掉8个字节的前导符和帧开始符,以太网帧的最小长度为64字节。

如果说以太网帧的最小长度64byte是由CSMA/CD限制所致,那最大长度1500byte又是处于什么考虑的呢?
IP头total length为两个byte,理论上IP packet可以有65535 byte,加上Ethernet Frame头和尾,可以有65535 +14 + 4 = 65553 byte。如果在10Mbps以太网上,将会占用共享链路长达50ms,这将严重影响其它主机的通信,特别是对延迟敏感的应用是无法接受的。
由于线路质量差而引起的丢包,发生在大包的概率也比小包概率大得多,所以大包在丢包率较高的线路上不是一个好的选择。
但是如果选择一个比较小的长度,传输效率又不高,拿TCP应用来说,如果选择以太网长度为218byte,TCP payload = 218 - Ethernet Header -IP Header - TCP Header=218-18 - 20 -20= 160 byte
那有效传输效率=160/218= 73%
而如果以太网长度为1518,那有效传输效率=1460/1518=96%
通过比较,选择较大的帧长度,有效传输效率更高,而更大的帧长度同时也会造成上述的问题,于是最终选择一个折衷的长度:1518 byte ! 对应的IP packet 就是 1500 byte,这就是最大传输单元MTU的由来。
C# TCP socket发送大数据包时,接收端和发送端数据不一致 服务端接收Receive不完全的更多相关文章
- 一次http请求,谁会先断开TCP连接?什么情况下客户端先断,什么情况下服务端先断?
我们有2台内部http服务(nginx): 201:这台服务器部署的服务是account.api.91160.com,这个服务是供前端页面调用: 202:这台服务器部署的服务是hdbs.api.911 ...
- TCP、UDP数据包大小的限制(UDP数据包一次发送多大为好)——数据帧的物理特性决定的,每层都有一个自己的数据头,层层递减
1.概述 首先要看TCP/IP协议,涉及到四层:链路层,网络层,传输层,应用层. 其中以太网(Ethernet)的数据帧在链路层 IP包在网络层 TCP或UDP包在传输层 TCP或UDP中的数据(Da ...
- 【传输协议】发送https请求,由于客户端jdk版本过高,服务端版本低。导致异常:javax.net.ssl.SSLHandshakeException: Server chose SSLv3, but that protocol version is not enabled or not supported by the client.
本地环境jdk为1.8,服务器使用jdk版本未知.但发送https请求,抛出如下异常,解决方案. 一:发送异常内容如下 javax.net.ssl.SSLHandshakeException: Ser ...
- Http协议:客户端提交数据给服务端和从服务端获得数据,像WebView也是向百度的服务端发出一条Http请求,服务端返回HTML页面,客户端(浏览器)解析后展示出页面
提交数据和获得数据的方式有很多,这里介绍一种,使用HttpURLConnection来向服务器提交数据或者获得数据. 获得数据: //传入网址,获得请求网页数据(XML文件数据或JSON文件数据) p ...
- TCP UDP 数据包过大导致分片情况
MTU大家都知道,是链路层中的网络对数据帧的一个限制,依然以以太网为例,MTU为1500个字节.一个IP数据报在以太网中 传输,如果它的长度大于该MTU值,就要进行分片传输,使得每片数据报的长度小于M ...
- (转)tcp和udp能否发送0字节的数据包
版权声明:本文为博主原创文章,未经博主允许不得转载. 转自:http://blog.csdn.net/wzx19840423/article/details/6643094 最近去一家牛逼的公司面试 ...
- 韩顺刚-tcp报文头协议详细分析第一包数据:序号是0,发送数据的长度是0,因为没有收到对端的数据,所以确认号是0, Syn的标志位设置成1,这里没有发送的数据,只发送TCP的20个字节的头部
TCP报文段首部格式 大部分TCP报文头部都是20个字节,有的数据包要加上选项. 上面一行代表4个字节,源端口和目的端口都是2个字节. TCP协议是面向字节流的协议 TCP是一段一段分块的发送数据的 ...
- TCP数据包的封包和拆包
//该段博文为引用,非原创. 封包和拆包 作者:fengge8ylf 博客:http://blog.csdn.net/fengge8ylf 对于基于TCP开发的通讯程序,有个很重要的问题需要解决,就 ...
- TCP传输小数据包效率问题(译自MSDN)
TCP传输小数据包效率问题(译自MSDN) http://www.ftpff.com/blog/?q=node/16 摘要:当使用TCP传输小型数据包时,程序的设计是相当重要的.如果在设计方案中不对T ...
随机推荐
- iOS --SQL的增加、删除、查找、修改
iOS对于数据库的操作:增加.删除.查找.修改 首先需要创建一个数据库:本程序的数据库是在火狐浏览器里的插件里写的微量型数据库 火狐找查找SQLite Manager的步骤: 第一步:在工具栏找到附加 ...
- Python:版本升级
Linux 上安装的python版本是2.6.6,不能满足我运行软件的要求,所以对python进行升级.现在要了解MySQL Fabric,需要使用Python 2.7,所以只能对现有版本进行升级了. ...
- kvm/qemu/libvirt学习笔记 (1) qemu/kvm/libvirt介绍及虚拟化环境的安装
kvm简介 kvm最初由Quramnet公司开发,2008年被RedHat公司收购.kvm全称基于内核的虚拟机(Kernel-based Virtual Machine),它是Linux的一个内核模块 ...
- linux命令-系统命令
1.查看Linux磁盘空间大小 df -lh Filesystem 容量 已用 可用 已用% 挂载点 /dev/hda8 11G 6.0G 4.4G 58% / /dev/shm 236M 0 236 ...
- IBM Bluemix体验:Containers进阶
上一篇中介绍了Bluemix的Containers服务以及如何使用自定义的docker image创建一个容器实例并对外提供服务.除了自定义镜像之外,Bluemix Containers还可以使用Do ...
- redis字符串
字符串类型是redis的基本类型 字符串数据类型的相关命令用于管理 redis 字符串值,基本语法如下:COMMAND KEY_NAME SET 和GET用于设置和读取key的值 1.SET key ...
- java url encoder 的一个问题
@RequestMapping(value = {"/search"}) public String errorPath(HttpServletResponse response, ...
- 利用sharding-jdbc分库分表
sharding-jdbc是当当开源的一款分库分表的数据访问层框架,能对mysql很方便的分库.分表,基本不用修改原有代码,只要配置一下即可,完整的配置参考以下内容: <?xml version ...
- [LeetCode] Find the Duplicate Number 寻找重复数
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...
- redis学习笔记
Redis 命令 Redis 命令用于在 redis 服务上执行操作. 要在 redis 服务上执行命令需要一个 redis 客户端.Redis 客户端在我们之前下载的的 redis 的安装包中. 语 ...