send与recv
socket的send和recv是同时支持TCP和UDP的。从这两个函数的设计可以看出,协议简单来说就是读写数据。
1.TCP情况下
socket的选项是SOCK_STREAM
。
send的返回值>0时,表示实际发送了多少字节。注意:只是copy到系统缓存里,系统决定什么时候会发送这些数据。
send的返回值==0时,这个在send空串时会发生,是正常的。
send的返回值<0时(只会等于-1吧),需要检查errno,当errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN
时,连接正常,可以稍后再试。其他的就是连接异常了。
recv的返回值>0时,表示实际接受到多少字节。
recv的返回值==0时,表示连接断开,也就是收到了FIN或者RST。
recv的返回值<0时,检查errno,和send类似。
2.UDP情况下
socket的选项是SOCK_DGRAM
。
send的返回值>0时,返回值应该等于发送的数据长度。如果send的数据大于MTU,会在IP层分片,到达目标机器后IP层重组。
send的返回值==0时,这个只在发送空串时出现。注意:真的会发送空数据的。
send的返回值<0时,检查errno,确定连接是否还正常。一般不会发生吧,UDP的send是直接发送出去的。
recv的返回值>0时,收到一个完整的数据包。这个完整性是有IP层保证的。
recv的返回值==0时,收到空包,这和TCP有很大不同。
recv的返回值<0时,检查errno,确定socket是否正常。
PS:UDP还有两个函数sendto
和recvfrom
。客户端在调用connect后,才能用send
和recv
,服务器端只能用sendto
和recvfrom
。
3.TCP和UDP
UDP无连接,无顺序,自然不能代替TCP。
TCP是流式协议,需要应用层确认数据是否接受完整,也不能代替UDP。
应用要同时支持两种协议,得在上层做包装。有个KCP,使用UDP模拟TCP。