Socket那些事儿

Posted 车小胖谈网络

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Socket那些事儿相关的知识,希望对你有一定的参考价值。

问题描述

服务端把客户端几次发的数据一起接受了,是怎么回事?

客户端是android,服务端是c#,手机监听手指一动,就把手指所在的那个点的位置发给服务端,服务端死循环接收,android可以保证一次是给服务端发一条数据,但是服务端把几次发的数据一起接受了。

 

正文

Socket是TCP呈现给用户编程的接口,没有编程经验的读者会有问题,什么是接口呢?

洗衣机上有很多按钮,比如电源开关、轻柔洗、暴力洗、漂水、脱水等等。这些按钮就是用户操控洗衣机的接口,用户可以提供输入参数,其实就是简单的编程,洗衣机就可以愉快地工作了。

如果没有这些按钮接口,洗衣机只能做小朋友捉迷藏的秘密基地,却不能提供洗衣功能。


Socket就是这一套编程接口函数的统称,用户操纵TCP工作的小工具集。

 

以Send( )为例,当用户调用这个接口发送函数且成功返回,用户的数据会立马发送到网络上去吗?

不一定。


Send ( )函数其实仅仅将用户数据copy 到TCP的发送缓存(Send Buffer),是一次从用户空间到内核空间的复制操作。至于TCP如何什么时候处理发送缓存的数据,这个是TCP的私事,用户无法干涉。

这就好比客户将快递包裹送到快递公司发送,快递公司什么时候运输,客户鞭长莫及无法左右。

 

TCP迟早要将发送缓存的数据发送掉,为什么不能立即发送,等谁呢?

TCP讲究高效的传输,用户扔几个字节到发送缓存,TCP就要乖乖地把它们运走?还要添加20字节的TCP头,20字节的IP头,甚至为了满足以太网最小64字节的要求,还要填充几个字节的“00”。忙了半天,就为了长途运输几个字节。TCP说,这个我不干,效率太低下!

 

TCP在等待用户多扔一些字节到发送缓存区,多少是多呢?

如果能够填满一个标准集装箱(MSS大小)、且TCP空闲,TCP会心满意足地发送一个标准集装箱。

如果用户的字节数据一直没有填满一个标准柜,那TCP就一直不发送吗?

也不是,TCP如果等一段时间(200ms),不管集装箱有没有填满,都会将集装箱发出去,为了减少客户的骂娘声!

 

从TCP的处理习惯可以看出,用户分批扔进发送缓存的字节数据,最后很有可能被塞进了一个标准集装箱发送。到达目的地后,被接收方客户一股脑取走,客户无法从物理意义上将不同批次的数据分离开来。

 

客户执意想让接收方能够分离不同批次的数据,可以采用以下几种方法:

  • 不同批次的数据之间有一个延迟,逼迫TCP将不同批次的数据装在独立的集装箱里运输

  • 不同批次的数据之间添加分隔符,接收方可以凭借分隔符,将不同批次的数据分拣出来

  • 发送方每次只发送一个批次的数据,等待对方应用程序响应报文到来,再发送下一个批次的数据,循环往复


个人认为第三种方法比较好,此外还要将Nagle算法关闭。 

以上是关于Socket那些事儿的主要内容,如果未能解决你的问题,请参考以下文章

zz酷客:tcpde那些事儿

Bugtags 那些事儿

FastDFS运维友好那些事儿

setTimeout那些事儿

《明朝那些事儿》全册

IMSI的那些事儿