浅谈Socket同步io

先说说阻塞式同步IO

Socket要实现通信,最简单的函数是Write和Read。而这两个函数在默认时都是阻塞式的。阻塞式的意思就是调用后会挂起线程,直到达成某一个目标才继续执行

这么做的坏处显而易见,服务器没法快速的和对个客户端同时进行通信了(或者说效率暴低)。

首先当然可以用异步io的方式,但这不是我们这段讨论的内容,同步解决的办法有这些。

Receive

使用多路复用的方法(Select,Epoll)

这个做法的原理就是每次收数据前,会看一下Socket有没有数据,没有数据,就不去Receive。这么做也就避免了阻塞,解放了线程。

Send

设置Socket的属性IsBlocking=false;

这时的socket成为了一个非阻塞的socket,每次调用Send时,如果没有数据可以发送或没有全部发送出去,会返回实际发送的字节数。

Send到底阻塞在哪里?

相对于Receive(别人不给我数据,我只能等)。Send为什么会在IsBlocking=true的时候阻塞比较长时间呢?这难道不是和写文件一样,只是一次确定的系统调用消耗吗?虽然实际应用中,不太会这么设置,这里我们还是想刨根问底研究下。

Send阻塞时间到底有哪几部分组成?

把数据从用户程序拷贝到发送缓冲区时间T1,如果发送缓冲区满了,就会阻塞直到缓冲区重新可用T2

T1是正比于数据量的,所以一般是非常短的时间。

T2就比较复杂了,而且可能会比较长。它受影响与缓冲区的大小,以及通信对端的速度。

缓冲区越大,T2的情况就不容易发生,T2理论上就比较短。而对端的速度造成影响的原因,主要是因为tcp滑动窗口的存在。通过write发送的数据,被放在发送缓冲并发给客户端,此时缓冲的数据并不会删除,一直到客户端ack了一个数据段。那么,如果客户端非常慢,就可能出现一直不ack服务器的数据,导致服务器缓冲区一直满负载,一直阻塞住,T2就爆了。

这种情况,我目前也没有很好的办法,只能设置一个超时时间(SendTimeout=500ms)补救下。

这里说道的内容,想具体了解的朋友可以参阅《TCP/IP卷一》

你可能感兴趣的:(网络)