网络编程(三)——数据的IO和复用

目录

1.IO函数

1.1 recv()

1.2 send()

1.3 readv()和writev()

1.4 recvmsg()和sendmsg()

1.5IO函数的比较

2.IO模型

2.1 阻塞IO模型

2.2 非阻塞IO模型

2.3 IO复用

2.4 信号驱动IO模型

3.select和pull机制

4.epoll机制

5.几种IO模型的选择


1.IO函数

1.1 recv()

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

从套接字s中接收数据到buf中,buf的长度为len,flag参数的定义如下

含义
MSG_DONTWAIT非阻塞操作,立即返回
MSG_ERRQUEUE错误消息从套接字错误队列接收
MSG_OOB接收带外数据
MSG_PEEK查看刻度数据,执行recv后,内核不会将这些数据丢弃
MSG_TRUNC返回所有数据,即使指定的缓冲区过小
MSG_WAITALL灯带所有的消息
MSG_CMSG_CLOEXECrecvmsg() only

recv通常用于TCP类型的套接字,UDP常用recvfrom,在UDP绑定地址跟端口后也可以使用recv.

recv函数从内核的接受缓冲区中复制数据到用户指定的缓冲区内,当内核中的数据比指定缓冲区大小小的时候,一般情况下会复制缓冲区中的所有内容到用户缓冲区,并返回数据长度。当内核的数据长度大于用户指定缓冲区大小的时候,内核会将接收缓冲区的数据按照用户指定的长度len复制到用户指定地址,然后将剩余数据下次调用接收函数的时候返回。

1.2 send()

#include <sys/types.h>
#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

当send返回的数据小于len时,表明缓冲区中仍然有部分数据没有发送,这时需要重新计算剩余没有发送的数据的长度。通常的剩余数据发送的方法是对原来的buf中的数据位置偏移已成功发送的字节数。

1.3 readv()和writev()

#include <sys/uio.h>

ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

struct iovec {
   void  *iov_base;    /* Starting address */
   size_t iov_len;     /* Number of bytes to transfer */
};

在调用readv的时候必须制定iov_base的长度.参数vector指向一块结构vector的内存,大小由iovcnt制定。readv()向量的结构如下图:

1.4 recvmsg()和sendmsg()

#include <sys/types.h>

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);

struct msghdr {
   void         *msg_name;       /* optional address */
   socklen_t     msg_namelen;    /* size of address */
   struct iovec *msg_iov;        /* scatter/gather array */
   size_t        msg_iovlen;     /* # elements in msg_iov */
   void         *msg_control;    /* ancillary data, see below */
   socklen_t     msg_controllen; /* ancillary data buffer len */
   int           msg_flags;      /* flags on received message */
};

recvmsg的含义如1.1表格所示。recvmsg的向量结构如下图所示:

1.5IO函数的比较

IO函数比较
名称任何描述符只对套接字描述符单个缓冲区多个缓冲区可选标志可选对方标志可选控制信息
read()/write()     
readv()/writev()     
recv()/send()    
recvfrom()/writeto()   
recvmsg()/sendmsg()  

 

使用IO的例子:

https://github.com/lixiangsheng2018/linux_network_programming/tree/master/chp9/send_recv

https://github.com/lixiangsheng2018/linux_network_programming/tree/master/chp9/readv_writev

2.IO模型

2.1 阻塞IO模型

在数据没有到来之前程序会一直等待,如下图

2.2 非阻塞IO模型

对每次请求,内核都不会阻塞,会立即返回,当没有数据的时候,会返回一个错误,如下图:

2.3 IO复用

在等待的时候计入超时时间,当超时时间没有到的时候跟阻塞IO一致,当超时时间到大仍没有数据到来系统会返回。

selsect函数会按照一定的时间轮询,直到有数据到来利用recvfrom将数据复制到应用层,如下图:

2.4 信号驱动IO模型

信号驱动IO模型在进程开始的时候注册一个信号处理的回调函数,进程继续进行,当信号发生时,利用注册的回调函数将到来的数据用recvfrom函数接收,如下图:

2.5 异步IO模型

异步IO与信号驱动IO相似,区别在于信号驱动IO当数据到来的时候,使用信号通知注册的信号处理函数,而异步IO在数据复制完成的时候才发动信号通知注册的信号处理函数,如下图:

 

3.select和pull机制

 

4.epoll机制

 

5.几种IO模型的选择

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值