send、recv、sendto和recvfrom函数解析
end、recv和sendto、recvfrom,⼀般情况下,send、recv在TCP协议下使⽤,sendto、recvfrom在UDP协议下使⽤,也可以在TCP协议下使⽤,不过⽤的很少。
1、send
这⾥只描述同步socket的send函数的执⾏流程。
s:套接字  |  buf:存储发送数据  |  len:发送数据长度
当调⽤该函数时,send先⽐较待发送数据的长度len和套接字s的发送缓冲的长度,如果len⼤于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len⼩于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完;如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就⽐较s的发送缓冲区的剩余空间和len,如果len⼤于剩余空间⼤⼩send就⼀直等待协议把s的发送缓冲中的数据发送完,如果len⼩于剩余空间⼤⼩send就仅仅把buf中的数据copy到剩余空间⾥(注意:并不是send把s的发送缓冲中的数据传到连接的另⼀端的,⽽是协议传的,send仅仅是把buf中的数据copy 到s的发送缓冲区的剩余空间⾥)。
如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就
返回SOCKET_ERROR;如果send在等待协议传送数据时⽹络断开的话,那么send函数也返回SOCKET_ERROR。
要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间⾥后它就返回了,但是此时这些数据并不⼀定马上被传到连接的另⼀端。如果协议在后续的传送过程中出现⽹络错误的话,那么下⼀个Socket函数就会返回SOCKET_ERROR。(每⼀个除send外的Socket函数在执⾏的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现⽹络错误,那么该Socket函数就返回SOCKET_ERROR)
注意:在Unix系统下,如果send在等待协议传送数据时⽹络断开的话,调⽤send的进程会接收到⼀个SIGPIPE信号,进程对该信号的默认处理是进程终⽌。
2、recv
这⾥只描述同步Socket的recv函数的执⾏流程。
s:套接字  |  buf:存储发送数据  |  len:发送数据长度
当应⽤程序调⽤recv函数时,recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现⽹络错误,那么recv函数返回SOCKET_ERROR;如果s的发送缓冲中没有数据
或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就⼀直等待,只到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能⼤于buf的长度,所以在这种情况下要调⽤⼏次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时⽹络中断了,那么它返回0。recv函数
注意:在Unix系统下,如果recv函数在等待协议接收数据时⽹络断开了,那么调⽤recv的进程会接收到⼀个SIGPIPE信号,进程对该信号的默认处理是进程终⽌。
3、sendto&recvfrom
在⽆连接的数据报socket⽅式下,由于本地socket并没有与远端机器建⽴连接,所以在发送数据时应指明⽬的地址,sendto()函数原型为:
int sendto(
int sockfd,
const void *msg,
int len,
unsigned int flags,
const struct sockaddr *to,
int tolen
);
该函数⽐send()函数多了两个参数,to表⽰⽬地机的IP地址和端⼝号信息,⽽tolen常常被赋值为sizeof(struct sockaddr)。Sendto 函数也返回实际发送的数据字节长度或在出现发送错误时返回-1。
recvfrom()的情况与sendto()类似,也需要⽬的地址,函数原型为:
int recvfrom(
int sockfd,
void *buf,
int len,
unsigned int lags,
struct sockaddr *from,
int *fromlen
);
from是⼀个struct sockaddr类型的变量,该变量保存源机的IP地址及端⼝号。fromlen常置为sizeof(struct sockaddr)。当recvfrom返回时,fromlen包含实际存⼊from中的数据字节数。recvfrom()函数返回接收到的字节数或当出现错误时返回-1,并置相应的errno。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。