网络编程中,recv/send、write/read函数各自的参数,返回值,区别

3 篇文章 0 订阅
2 篇文章 0 订阅

对于网络编程这一块,面试必考,但……真正工作不见得接触到几次,于是我又忘了,今天整理一下发送和接受时候的几个函数

一、recv

函数原型:
int recv( _In_ SOCKET s, _Out_ char *buf, _In_ int len, _In_ int flags);

参数:

In SOCKET s:就是Socket本身,这没什么好说的,需要注意的是server_socket与client_socket之间的联系和区分

Out char *buf:接受数据的缓存区,传入的是地址或者指针。在成功调用recv后,接收到的数据就存放在这里

In int len:缓存区的长度,整型。

In int flags:某个标志,默认取0。也有其他的,初学者写0就可以。flags参数表如下:

flags说明recvsend
MSG_DONTROUTE绕过路由表查找
MSG_DONTWAIT仅本操作非阻塞
MSG_OOB发送或接收带外数据
MSG_PEEK窥看外来消息
MSG_WAITALL等待所有数据
函数说明:

在调用recv函数之后,socket执行了下列操作

  1. 检查socket的发送缓存区,并等待之前的数据发送完,期间出现网络错误则返回SOCKET_ERROR;
  2. 检查套接字s的接收缓冲区,并等待数据接收完毕;
  3. 当数据接收完毕,recv函数就把s的接收缓冲区中的数据copy到recv_buf中。
注意事项:
  • 协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。
  • recv函数仅仅是copy数据,真正的接收数据是协议来完成的。
  • recv函数返回其实际copy的字节数,如果recv在copy时出错,那么它返回SOCKET_ERROR。如果recv函数在等待协议接收数据时网络中断了,那么它返回0。
  • 在unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用 recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
返回值:
返回值说明
SOCKET_ERRORSocket错误(见上文)
>0调用正常,返回接收到的字节数,非传入的recv_buf_len
0socket关闭
<1各种错误

二、send

函数原型:
int send( SOCKET s,char *buf,int len,int flags );

参数:

In SOCKET s:就是Socket本身,这没什么好说的,需要注意的是server_socket与client_socket之间的联系和区分

Out char *buf:发送的缓存区,传入的是地址或者指针。在这里存放等待发送的数据。

In int len:缓存区的长度,整型。

In int flags:某个标志,默认取0。也有其他的,初学者写0就可以。flags参数表如下:

flags说明recvsend
MSG_DONTROUTE绕过路由表查找
MSG_DONTWAIT仅本操作非阻塞
MSG_OOB发送或接收带外数据
MSG_PEEK窥看外来消息
MSG_WAITALL等待所有数据

需要注意的是,send的参数与recv参数大致相同,recv的buf在调用后会被装入接收到的消息,而send的buf调用后没有变化

函数说明:

在调用send函数之后,socket执行了下列操作

  1. 参数len(即待发送数据的长度)大于 socket发送缓存区的长度n,则返回SOCKET_ERROR。(数据太多了,无法copy过去)
  2. 检查套接字s是否正在发送数据,若是则等待发送完毕。(注意不是检查发送缓存区是否有数据)
  3. 对比参数len(即待发送数据的长度)socket发送缓存区剩余长度n-x,判断:
    (注意此时发送缓存区可能有数据,只是并未开始发送)
    • 如果剩余长度不能塞下buf,则socket等待发送缓存区发送完毕;
    • 如果能塞下,则把待发送数据copy到发送缓存区的剩余空间,并返回实际copy的字节数。(该返回值不一定等于len)
注意事项:
  • 将待发送数据copy到发送缓存区时,若copy出错,则返回SOCKET_ERROR;若socket在等待发送缓存区发送的时候网络错误,也返回SOCKET_ERROR。
  • 待发送数据copy完之后,send函数就返回了,数据还没有send出去,若此时遇到网络错误,则会在下一次socket调用时候返回SOCKET_ERROR。
  • 在unix系统下,如果send在等待协议传送数据时网络断开,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的处理是进程终止。
返回值:
返回值说明
SOCKET_ERROR错误(见上文)
>0调用正常,返回实际发送的字节数,非传入的len
0socket关闭
<1各种错误

三、read与write

read/write在socket实现部分与send/recv几乎一致,故简要介绍
函数原型:

ssize_t read(int fd, void *buf, size_t nbytes);
ssize_t write(int fd, const void *buf, size_t nbytes);

参数:

int fd:就是Socket本身,这没什么好说的,需要注意的是server_socket与client_socket之间的联系和区分

void *buf:数据的缓存区,传入的是地址或者指针。

size_t nbytes:缓存区的长度。

函数说明:
  1. Linux在建立好Tcp之后,socket可以当作文件描述符来使用,因此read/write可以读取文件,也可以读取套接字。
  2. size_t 是通过 typedef 声明的 unsigned int 类型;
    ssize_t 在 “size_t” 前面加了一个"s",代表 signed,即 ssize_t 是通过 typedef 声明的 signed int 类型。
  3. write函数返回值不一定是全部数据的字节数,有可能只有一部分,即write函数不保证能全部传输完数据,需要while不断传输,while时需要同步更改len
返回值:
返回值说明
>0调用正常,返回写入或者读取的字节数,非传入的recv_buf_len。write函数返回值不一定是全部数据的字节数
0read时候遇到文件结束符
<1各种错误
EINTR中断错误
EPIPE网络错误
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值