网络编程一些零碎知识点

阻塞网络IO也是有陷阱的:类似死锁。比如服务器和客户端都阻塞到了send。
本质原因是内核缓冲区大小有限。在发个大的包的时候服务器可能会一次收一部分(buf的大小),然后直接发送,但是这时客户端还阻塞在send上,于是就完全被阻塞住了。简单的解决办法就是尽量不要依赖内核缓冲区,自己做一个缓冲区,一个包要一次收完。

另外,在自己定义的协议里可能会标识包的大小,这时如果有恶意就可能人为把这个大小设置的非常大,然后服务器可能在准备对应的缓冲区或内存空间时就会崩溃。所以一切有可能溢出的地方都要做边界检查。

TCP自连接是有可能发生的,解决办法就是在连接时检查两侧端口是否相同。

sysctl命令可以查看一些系统参数,sysctl -a 会显示所有可读参数。

在发完数据之后可以关闭写端,但是一定要去读接收方的数据,直到读到EOF,这样保证对面读完了,然后才能close。这样实质上是等待对面先关闭了socket。
有恶意的情况下或者对面有bug,始终不关闭socket,为了保证不阻塞发送方应当设置超时。

在接收端莫名关闭时,发送端会接受SIGPIPE,默认行为是自动终止,所以要记得ignore SIGPIPE。

在同时连接数少的时候one thread per connection模型反而比IO multiplexing吞吐量更大,因为不需要进行阻塞等待(epoll_wait),但是并发量大时就明显处于劣势了。
而且IO multiplexing和阻塞IO配合使用时,一旦一个IO被阻塞,那么整个事件循环就完蛋了。而且在一个事件结束后要记得unregister掉那个描述符,不然会造成busy loop。

在select中即使返回可读在读时也有可能阻塞,accept时即使socket可读也有可能阻塞,所以非阻塞IO是非常必要的。

在写非阻塞IO写的时候要注意考虑short write的情况,同时在设计buffer时要考虑sink slow的情况。应该为buffer设置一个安全水位,防止过大溢出。

connect即使连接失败也会可读可写,所以需要通过getsockopt来判断一下连接是否成功了。