前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >UNPv1第十三章:高级IO

UNPv1第十三章:高级IO

作者头像
提莫队长
发布2019-02-21 10:55:53
7870
发布2019-02-21 10:55:53
举报
文章被收录于专栏:刘晓杰刘晓杰

1.套接字超时

涉及套接字上的I/O操作设置超时的方法有三种方法:

  1. 调用alarm,在到达指定时间时产生SIGALRM信号
  2. 使用select阻塞在等待I/O上,select内部有一个时间限制,以此代替在read或write调用上阻塞
  3. 使用新的SO_RCVTIMEO和SO_SNDTIMEO套接字选项

前两种技术可以用于任何描述字,而第三种只能用于套接口描述字。

2.recv和send函数

这两个函数和标准的read和write函数都类似,不过多了一个附加参数

代码语言:javascript
复制
#include <sys/socket.h>
sszie_t recv(int sockfd, void * buff, size_t nbytes, int flags); 
ssize_t send(int sockfd, void * buff, size_t nbytes, int flags);
//返回: 成功返回读入或写出的字节数,出错返回-1

flag在设计上存在一个基本问题:它是按值传递的,而不是值-结果参数,因此它只能从进程向内核传递标志,内核不能向进程传递标志。

3.readv和writev函数(分散读,集中写)

代码语言:javascript
复制
#include <sys/uio.h>
ssize_t readv(int filedes, const struct iovec * iov, int iovcnt);
ssize_t writev(int filedes, const struct iovec * iov, int iovcnt);
 //返回: 读到或写出的字节数,出错时为-1

两个函数的第二个参数都是一个指向iovec结构的数组的指针,在

代码语言:javascript
复制
struct iovec {
  void * iov_base; /* starting address of buffer */
  size_t iov_len; /* size of buffer */
}

readv和writev函数可以用于任何描述字,不仅限于套接口描述字,而且writev是一个原子操作。

4.recvmsg和sendmsg函数

这两个函数是最通用的I/O函数,实际上,可以用recvmsg代替read, readv, recv, recvfrom. 类似的,各种输出函数可以用sendmsg取代。

代码语言:javascript
复制
#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr * msg, int flags); 
ssize_t sendmsg(int sockfd, struct msghdr * msg, int flags);
//返回: 成功时为读入或写出的字节数,出错时为-1

两个函数把大部分参数都包装到一个msghdr结构中:

代码语言:javascript
复制
struct msghdr {
   void         *msg_name;        /* protocol address */
   socklen_t     msg_namelen;     /* size of protocol address */
   struct iovec    *msg_iov;         /* scatter/gather array */
   int           msg_iovlen;      /* # elements in msg_iov */
   void         *msg_control;     /* ancillary data (cmsghdr struct) */
   socklen_t     msg_controllen;  /* length of ancillary data */
   int           msg_flags;       /* flags returned by recvmsg() */
};

5.辅助数据

辅助数据(ancillary data)可以通过sendmsg和recvmsg这两个函数,使用msghdr结构中的msg_contorl和msg_controllen成员发送和接收。 辅助数据的另一种叫法是控制信息(control information) 辅助数据是一个或多个辅助数据对象组成,每个对象由一个cmsghdr结构开头,该结构在

代码语言:javascript
复制
struct cmsghdr {
   socklen_t  cmsg_len;   /* length in bytes, including this structure */
   int        cmsg_level; /* originating protocol */
   int        cmsg_type;  /* protocol-specific type */
    /* followed by unsigned char cmsg_data[] */
};

下图为在Unix域套接字上的cmsghdr结构:

这里写图片描述
这里写图片描述

6 排队的数据量

在不读出数据的情况下,如何知道一个套接口的接收队列中有多少数据可读呢?有三种方法:

  1. 如果在没有数据可读时还有其他事情要做,为了不阻塞在内核中,可以使用非阻塞I/O
  2. 如果想检查一下数据而使数据仍留在接收队列中,可以使用MSG_PEEK标志。如果想这样做,但又不能肯定是否有数据可读,可以把这个标志和非阻塞套接口相结合,或与MSG_DONTWAIT标志结合使用。
  3. 一些实现支持ioctl的FIONREAD命令

7.套接口和标准I/O

标准I/O库执行三种缓冲:

  1. 完全缓冲意味着只有在以下情况时才进行I/O:缓冲区满,进程明确地调用fflush或进程调用exit终止。标准I/O缓冲区大小通常为8192字节。
  2. 行缓冲意味着在以下情况时进行I/O:遇到一个换行符,进程调用fflush或进程调用exit终止。
  3. 不缓冲意味着每次调用标准I/O输出函数时都进行I/O

大多数Unix中标准I/O库的实现遵循了以下规则:

  1. 标准错误输出总是不缓冲。
  2. 标准输入和标准输出是全缓冲的。除非他们是一个终端设备,那样的话他们是行缓冲。
  3. 其他的流都是全缓冲的,除非他们是一个终端设备,那样的话他们是行缓冲。

既然套接口不是终端设备,上面str_echo函数的问题就在于输出流(fpout)是全缓冲的。 有两种解决方法:调用setvbuf将输出流强制成行缓冲的,或者在每次fputs之后调用fflush强制输出回射行。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016年04月26日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.套接字超时
  • 2.recv和send函数
  • 3.readv和writev函数(分散读,集中写)
  • 4.recvmsg和sendmsg函数
  • 5.辅助数据
  • 6 排队的数据量
  • 7.套接口和标准I/O
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档