网络编程常用I/O函数

read/write

 

 

readv/writev

“对数据进行整合传轮及发送的函数。”
也就是说,通过writev 函数可以将分散保存在多个缓冲中的数据一并发送,通过readv函数可以由多个缓冲分别接收。因此,适当使用这2个函数可以减少I/O函数的调用次数。下面先介绍writev 函数。

#include <sys/uio.h>
ssize t writev(int filedes, const struct iovec * iov, int iovcnt);
//成功时返回发送的字节数,失败时返回-1 。
 
#filedes 表示数据传输对象的套接字文件描述符。但该函数并不只限于套接字,因此,可以像read函数一样向其传递文件或标准输出描述符。
#iov iovec结构体数组的地址值,结构体 iovec 中包含待发送数据的位置和大小信息。
#iovcnt 向第二个参数传递的数组长度。

合理使用readv & writev 函数
哪种情况适合使用readv和writev函数? 实际上,能使用该函数的所有情况都适用。例如, 需要传输的数据分别位于不同缓冲(数组)时,需要多次调用write函数。此时可以通过1 次writev函数调用替代操作,当然会提高效率。同样,需要将输入缓冲中的数据读入不同位置时,可以不必多次调用read函数,而是利用1 次readv函数就能大大提高效率。

即使仅从C语言角度看,减少函数调用次数也能相应提高性能。但其更大的意义在于减少数据包个数。假设为了提高效率而在服务器端明确阻止了Nagle算法。其实writev函数在不采用Nagle算法时更有价值,如图所示。

上述示例中待发送的数据分别存在3个不同的地方,此时如果使用write 函数则需要3次函数调用。但若为提高速度而关闭了Nagl哆垃~. 则极有可能通过3个数据包传递数据。反之,若使用writev函数将所有数据一次性写入输出缓冲,则很有可能仅通过1个数据包传输数据。所以wri tev 函数和readv函数非常有用。

再考虑一种情况: 将不同位置的数据按照发送顺序移动(复制)到l个大数组,并通过1 次write函数调用进行传输。这种方式是否与调用writev函数的效果相同?当然! 但使用writev函数更为便利。因此,如果遇到writev 函数和readv函数的适用情况,希望各位不要错过机会。
参考:https://blog.csdn.net/qq_40732350/article/details/88980011

recv/send

#include <sys/socket.h>
ssize_t recv(int sockfd, void* buf, size_t nbytes, int flags);
//成功时返回接收的字节数(收到EDF 时返回0)' 失败时返回-1 。
#sockfd 表示数据接收对象的连接的套接字文件描述符。
#buf    保存接收数据的缓冲地址值。
#nbytes 可接收的最大字节数。
#flags  接收数据时指定的可选项信息。
#include <sys/socket.h>
ssize_t send(int sockfd, const void * buf, size_t nbytes, int flags);
//成功时返回发送的字节数,失败时返回-1。
#sockfd 表示与数据传输对象的连接的套接字文件描述符。
#buf    保存待传输数据的缓冲地址值。
#nbytes 待传输的字节数。
#flags  传输数据时指定的可选项信息。

由于不能绑定IP地址,所以只能借助于connect来实现连接和发送和接收信息。

 

 

参考:https://blog.csdn.net/qq_40732350/article/details/88980011

 

recvmsg/sendmsg

#include <sys/socket.h>
ssize_t recvmsg(int socket,      struct msghdr *message,   int   flags);
ssize_t sendmsg (int __fd, const struct msghdr *__message, int __flags);

 

 

struct msghdr
{
    void *msg_name;		    /*源地址  */
    socklen_t msg_namelen;	/* 地址长度  */

    struct iovec *msg_iov;	/*接收或发送数据的数组 */
    size_t msg_iovlen;		/*msg_iov数组的元素数量*/

    void *msg_control;		/*指向缓冲区*/
    size_t msg_controllen;	/*指向缓冲区的大小*/

    int msg_flags;          /*操作方式*/
};

 

 

参考:https://wenku.baidu.com/view/7a8a522158fb770bf78a55cf.html

 

 

sendto/recvfrom

基于UDP 的数据I/O函数

#include <sys/socket.h>
ssize_t sendto(int sock, void *buff, size_t nbytes, int flags, struct sockaddr *to, socklen_t addrlen);
//成功时返回传输的字节数,失败时返回-1 。
 
#sock       用于传输数据的UDP套接字文件描述符。
#buff       保存待传输数据的缓冲地址值。
#nbytes     待传输的数据长度,以字节为单位。
#flags      可选项参数,若没有则传递0。
#to         存有目标地址信息的sockaddr结构体变量的地址值。
#addrlen    传递给参数to的地址值结构体变量长度。
#include <sys/socket.h>
ssize_t recvfrom(int sock, void *buff, size_t nbytes, int flags, struct sockaddr * from, socklen_t *addrlen);
成功时返回接收的字节数,失败时返回-1。
 
#sock    用于接收数据的UDP套接字文件描述符。
#buff    保存接收数据的缓冲地址值。
#nbytes  可接收的最大字节数,故无法超过参数butt所指的缓冲大小。
#flags   可选项参数,若没有则传入0 。
#from    存有发送端地址信息的sockadd结构体体变量的地址值。
#addrlen 保存参数from的结构体变量长度的变量地址值。

 

参考:https://blog.csdn.net/qq_40732350/article/details/88945957

 

 

 

 

 

 

 

 

 

函数read()/write()和readv()/writev()可以对所有的文件描述符使用:recv()/send), recvfrom()/writeto0)和recvmsg/sendmsg只能操作套接字描述符。
函数readv()/writev()和recvmsg()/sendmsg)可以操作多个缓冲区, read()/write()、recv()/send()和recvfrom()/sendto()只能操作单个缓冲区。
函数recv()/send()、recvfrom()/sendto()和recvmsg()/sendmsg()具有可选标志。
函数recvfrom()/sendto()和recvmsg()/sendmsg()可以选择对方的IP地址。
函数recvmsg()/sendmsg()有可选择的控制信心,能进行高级操作。

                                                                             IO函数比较

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值