一、描述符就绪条件

对于引起select返回套接字“就绪”的条件我们必须讨论得更明确:

(1)满足一下塞个条件中的仍和一个时,一个套接字准备好读。

a)该套接字接收缓冲区中的数据字节数不大于等于套接字接收缓冲区低水位标记的当前大小。相关SO_RCVLOWAT默认值为1

b)该连接的读半部关闭(也就接收了FIN的TCP连接)。对这样的套接字读操作将不阻塞并返回0(返回EOF)

c)该套接字是一个监听套接字且已完成的连接数不为0(accept不阻塞)

d)其上有一个套接字错误待处理。

(2)下列四个条件中任何一个满足时,一个套接字准备好写。

a)该套接字发送发送缓冲区中的可用空间字节数大于等于套接字发送缓冲区低水位标记的当前大小,

并且该套接字已连接,或者该套接字不需要连接。相关SO_SNDLOWAT默认2048

b)该链接写半部关闭。写操作将产生SIGPIPE

c)使用非阻塞式connect套接字已建立连接,或者connect已经以失败告终

d)其上有一个套接字错误待处理。

(3)如果一个套接字存在带外数据或者仍处于带外标记,那么它有异常条件待处理。

二、shutdown函数

#include <sys/socket.h>

int shutdown(int sockfd, int howto);
返回:成功为0,出错-
sockfd:套接字描述符
howto:
SHUT_RD:关闭连接的读这一半,套接字不再有数据可接收
SHUT_WR:关闭连接的写这一半,套接字不再有数据可发送
SHUT_RDWR:连接的读半部和写半部都关闭

str_cli函数(再修订版):

 #include "unp.h"

 void
str_cli(FILE *fp, int sockfd)
{
int maxfdp1, stdineof;
fd_set rset;
char buf[MAXLINE];
int n; stdineof = ;
FD_ZERO(&rset);
for( ; ;) {
if(stdineof == )
FD_SET(fileno(fp), &rset);
FD_SET(sockfd, &rset);
maxfdp1 = max(fileno(fp), sockfd) + ;
Select(maxfdp1, &rset, NULL, NULL, NULL);
if(FD_ISSET(sockfd, &rset)) {
if((n = Read(sockfd, buf, MAXLINE)) == ) {
if(stdineof == )
return;
else
err_quit("str_cli: server terminated prematurely");
}
Write(fileno(stdout), buf, n);
}
if(FD_ISSET(fileno(fp), &rset)) {
if((n = Read(fileno(fp), buf, MAXLINE)) == ) {
stdineof = ;
Shutdown(sockfd, SHUT_WR);
FD_CLR(fileno(fp), &rset);
continue;
}
Writen(sockfd, buf, n);
}
}
}

str_cli

三、pselect函数

#include <sys/select.h>
#include <signal.h>
#include <time.h> int pselect(int maxfdp1, fd_set *readset, fd_set *writeset,
fd_set *exceptset, const struct timespec *timeout, const sigset_t *sigmask);
返回:若有就绪描述符则为其数目,若超时则为0,若出错则为-1
maxfdp1:最大描述符集+1
readset:读集
writeset:写集
exceptset:异常集
timeout:延时
sigmask:掩码

pselect()用来等待文件描述词状态的改变,和select()类似,它增加了超时值的精度,并且可以在等待文件描述符“准备好”的同时指定一组信号掩码。

四、poll函数

#include <poll.h>

int poll(struct pollfd *fdarray, unsigned long nfds, int timeout);
返回:若有就绪描述符则为其数目,若超时则为0,若出错则为-1
struct pollfd {
int fd;
short events;
short revents;
}
fdarray:指向结构数组第一个元素的指针
nfds:用于标记数组fds中的结构体元素的总数量
timeout:是poll函数调用阻塞的时间,单位:毫秒

poll的百度示例,和select类似

 #include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <poll.h>
#include <fcntl.h>
#include <unistd.h> #define MAX_BUFFER_SIZE 1024
#define IN_FILES 3
#define TIME_DELAY 60*5
#define MAX(a,b) ((a>b)?(a):(b)) int
main(int argc, char **argv)
{
struct pollfd fds[IN_FILES];
char buf[MAX_BUFFER_SIZE];
int i, res, real_read, maxfd;
fds[].fd = ;
if((fds[].fd = open("data1", O_RDONLY|O_NONBLOCK)) < ) {
fprintf(stderr, "open data1 error:%s", strerror(errno));
return ;
}
if((fds[].fd = open("data2", O_RDONLY|O_NONBLOCK)) < ) {
fprintf(stderr, "open data2 error:%s", strerror(errno));
return ;
} for(i=;i<IN_FILES;i++)
fds[i].events = POLLIN; while(fds[].events || fds[].events || fds[].events) {
if(poll(fds, IN_FILES, TIME_DELAY) <= ) {
printf("Poll error\n");
return ;
}
for(i=;i<IN_FILES;i++) {
if(fds[i].revents) {
memset(buf, , MAX_BUFFER_SIZE);
real_read = read(fds[i].fd, buf, MAX_BUFFER_SIZE);
if(real_read < ) {
if(errno != EAGAIN)
return ;
} else if(!real_read) {
close(fds[i].fd);
fds[i].events = ;
} else {
if(i == ) {
if((buf[] == 'q') || (buf[] == 'Q'))
return ;
} else {
buf[real_read] = '\0';
printf("%s", buf);
}
}
} }
}
exit();
}

poll

 #include "unp.h"
#include <limits.h> int
main(int argc, char **argv)
{
int i, maxi, listenfd, connfd, sockfd;
int nready;
ssize_t n;
char buf[MAXLINE];
socklen_t clilen;
struct pollfd client[OPEN_MAX];
struct sockaddr_in cliaddr, servaddr; listenfd = Socket(AF_INET, SOCK_STREAM, ); bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT); Bind(listenfd, (SA *)&servaddr, sizeof(servaddr)); Listen(listenfd, LISTENQ); client[].fd = listenfd;
client[].events = POLLRDNORM;
for(i=;i<OPEN_MAX;i++)
client[i].fd = -;
maxi = ; for( ; ; ) {
nready = Poll(client, maxi+, INFTIM); if(client[].revents & POLLRDNORM) {
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *)&cliaddr, &clilen); for(i=;i<OPEN_MAX;i++)
if(client[i].fd < ) {
client[i].fd = connfd;
break;
}
if(i == OPEN_MAX)
err_quit("too many clients"); client[i].events = POLLRDNORM;
if(i > maxi)
maxi = i; if(--nready <= )
continue;
}
for(i = ;i<=maxi;i++) {
if((sockfd = client[i].fd) < )
continue;
if(client[i].revents & (POLLRDNORM | POLLERR)) {
if((n = read(sockfd, buf, MAXLINE)) < ) {
if(errno = ECONNRESET) {
Close(sockfd);
client[i].fd = -;
} else
err_sys("read error");
} else if(n == ) {
Close(sockfd);
client[i].fd = -;
} else
Writen(sockfd, buf, n); if(--nready <= )
break;
}
}
}
}

tcp

UNP学习第六章(二)的更多相关文章

  1. UNP学习第六章select

    一.I/O复用典型的网络应用场合 当客户处理多个描述字时,必须使用I/O复用,这在前一段中已做了描述. 一个客户同时处理多个套接口时可能的,但很少出现. 如果一个TCP服务器既要处理监听套接口,又要处 ...

  2. 201671010140. 2016-2017-2 《Java程序设计》java学习第六章

    java学习第六章    本周对与java中的接口,lambda表达式与内部类进行了学习,以下是我在学习中的一些体会:    1.接口: <1>.接口中的所有常量必须是public sta ...

  3. Java基础知识二次学习--第六章 常用类

    第六章 常用类   时间:2017年4月26日16:14:49~2017年4月26日16:56:02 章节:06章_01节~06章_06节 视频长度:20:57+1:15+8:44+1:26+11:2 ...

  4. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  5. 【转载】Gradle学习 第六章:构建脚本基础

    转载地址:http://ask.android-studio.org/?/article/11 6.1. Projects and tasks 项目和任务Everything in Gradle si ...

  6. C#高级编程 (第六版) 学习 第六章:运算符和类型强制转换

    第六章 运算符和类型强制转换 1,运算符 类别 运算符 算术运算符 + - * / % 逻辑运算符 & | ^ ~ && || ! 字符串连接运算符 + 增量和减量运算符 ++ ...

  7. UNP学习第五章(二)

    一.POSIX信号处理 信号:告知某进程发生了某个事件的通知(软中断),通常是异步的. 信号可以:由进程发给另一个进程,由内核发给某个进程. 设置信号处理办法,有三个选择: 1.写一个函数,在信号发生 ...

  8. Android的学习第六章(布局二--RelativeLayout)

    今天我们来说一下Android布局中的Relativelayout布局(相对布局) 根据英译过来意思是相对布局,很容易理解,这一样布局使用的是元素与元素之间的微调做到布局的 含义:通过元素与元素之间的 ...

  9. 深度学习框架PyTorch一书的学习-第六章-实战指南

    参考:https://github.com/chenyuntc/pytorch-book/tree/v1.0/chapter6-实战指南 希望大家直接到上面的网址去查看代码,下面是本人的笔记 将上面地 ...

随机推荐

  1. JS中的getter和setter

    对象有两种属性:(1)数据属性,就是我们经常使用的属性(2)访问器属性,也称存取器属性 存取器属性就是一组获取和设置值的函数.getter负责获取值,它不带任何参数.setter负责设置值,在它的函数 ...

  2. 【2019 Multi-University Training Contest 4】

    01:https://www.cnblogs.com/myx12345/p/11644076.html 02: 03:https://www.cnblogs.com/myx12345/p/116478 ...

  3. vue循环渲染变量类样式

    由于需求的需要,将五种不同的颜色样式通过v-for进行遍历渲染,所以我这里采用绑定类函数进行判断方式.代码: 效果: 灵感来自:https://www.jianshu.com/p/33e181be3d ...

  4. [CSP-S模拟测试]:虎(DFS+贪心)

    题目传送门(内部题15) 输入格式 第一行一个整数$n$,代表点数接下来$n-1$行,每行三个数$x,y,z$,代表点$i$与$x$之间有一条边,若$y$为$0$代表初始为白色,否则为黑色,若$z$为 ...

  5. Ubuntu编译ruby

    要用sass,需要ruby2.0以上版本 ubuntu升级ruby到2.1 1.安装前更新: sudo apt-get -y update sudo apt-get install cmake sud ...

  6. (转)Windows下安装Docker, GitBash环境配置

    转:https://blog.csdn.net/chengly0129/article/details/68944269 官网介绍: https://docs.docker.com/toolbox/t ...

  7. gradle spring 配置解释

    plugins { id 'java' id 'eclipse' id 'idea' # 统一springboot版本号 id 'org.springframework.boot' version ' ...

  8. Django-自定义用户模型

    Django最方便的一点,是自带用户系统,但有些情况下,不符合项目需求, 原因1.我们有时候需要自定义一些字段,或者删除Django自带字段,2.我们有时候需要定义哪些字段是必填的,登陆时的用户名是哪 ...

  9. appium常见问题11_小米手机初次启动app,报错255“Requires permission android.permission.WRITE_SECURE_SETTINGS”

    问题: 新申请的测试机到啦,申请机型是小米9.打开开发者模式.USB调试后,连接电脑,准备跑一下自动化脚本.但是在pycharm中点击run后,出现报错,报错code:255,提示“Requires ...

  10. <读书笔记>JavaScript系列之7种创建对象(面向对象)

    写在前面: 以下三选一: 阅读博文JavaScript 对象详解. 阅读<JavaScript权威指南>第6章. 阅读<JavaScript高级程序设计>第6章. 注意:只需要 ...