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那些事儿的主要内容,如果未能解决你的问题,请参考以下文章