参考:https://blog.csdn.net/wangzhida2008/article/details/72901938 文章整理。
int send( SOCKET s, const char FAR *buf, int len, int flags );
send函数是将数据拷贝到socket发送缓冲区中。
拷贝过程中存在各种情况:
假设socket发送缓冲区的长度为 sendLength;
比较拷贝数据的大小len与发送缓冲区的大小sendLength的值,
1、如果len>sendLength,则函数返回SOCKET_ERROR;
------要拷贝的数据都超过了缓冲区大小了,所以报错!
2、如果len<=sendLength,send检查协议是否在发送缓冲区中的数据
1) 如果在发,就等待数据发送完成;
2) 如果没在发送,或者缓冲区中没有数据,send比较len和发送缓冲区剩余空间 leftLength大小
i)如果len >leftLength,等待协议把发送缓冲区的数据发送完成;
---------虽然没在发送,尽管总的空间时够的,但是,剩余空间不足,只能等了
ii)如果len<leftLength,send把buf中的数据拷贝到剩余空间里。
----------- 空间够了,而且也没有在发送数据,趁空闲把数据拷贝到缓冲区。
a)拷贝完成,返回实际拷贝的字节数;
b)拷贝出错,返回SOCKET_ERROR;
c)send在等待协议传送数据时,网络断开,返回SOCKET_ERROR.
------不是拷贝出错,而是等待协议传送时,网络断开,即网络出错。
要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执 行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回 SOCKET_ERROR)
在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
int recv( SOCKET s, char FAR *buf, int len, int flags );
recv函数将数据从缓冲区中拷贝到指定buf中;
拷贝过程中存在多种情况:
1、调用recv函数时,recv先等待s的发送缓冲区中数据被协议传送完成;
1)协议在传送数据过程中出现网络错误,则recv函数返回SOCKET_ERROR
-------每一个除send外的Socket函数在执 行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续, 如果在等待时出现网络错误,那么该Socket函数就返回 SOCKET_ERROR
2、如果缓冲区中没有数据或者数据已经被协议成功发送完成后
1)recv检查套接字s的接收缓冲区
i)接收缓冲区中没有数据或者协议正在接收数据,recv一直等待,直到协议把数据接收完毕。
a)接收完毕后,recv函数就把s的接收缓冲区中数据拷贝到buf中,recv函数返回的是实际拷贝的字节数。
------协议接收到的数据可能大于buf的长度,所以此时需要多调用几次recv函数才能把s的接收
缓冲区的数据拷贝完。
-------recv在拷贝时出错,则函数SOCKET_ERROR,如果recv函数在等待协议接收数据时网络中断了,则返回0.
注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。