一、描述符就绪条件

对于引起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. 【TCP】tcp协议通信中io

    阻塞IO recv,接收数据,若没有,将阻塞, 当对方发数据来后,linux内核缓冲区得到数据, 内核数据复制到recv()调用所在的用户空间, 阻塞解除,进行下一步处理, 非阻塞IO 轮询调用rec ...

  2. mybatis源码分析之04Mapper接口的动态代理

    在工作中,使用mybatis操作数据库,只需要提供一个接口类,定义一些方法,然后调用接口里面的方法就可以CRUD,感觉是牛了一逼! 该篇就是记录一下,mybatis是如何完成这波骚操作的,即分析我们测 ...

  3. MySQL索引优化之双表示例

    select * from tableA a left join tableB b on a.f_id = b.id; 索引建tableB表上面, 因为left join 注定左表全都有,所以应该关心 ...

  4. springmvc对象作为 目标方法的参数。

    /** * Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配, 自动为该对象填充属性值.支持级联属性. * 如:dept.deptId.dept.address.tel 等 */ ...

  5. 【BZOJ1801】【DTOJ2004】 [Ahoi2009]chess 中国象棋 【DP】

    题解: 首先知道一个性质,每一行每一列都最多有两个炮 那么很显然是DP 设F[i][j][k]表示前i行,有j列有一个炮,有k列有两个炮,那么转移式子为 这一行什么都不做:f[i][j][k]=f[i ...

  6. 前端每日实战:33# 视频演示如何用纯 CSS 创作牛奶文字变换效果

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/MGNWOm 可交互视频教程 此视频 ...

  7. 【SpingBoot】 测试如何使用SpringBoot搭建一个简单后台1

    很久没写博客了,最近接到一个组内的测试开发任务是做一个使用SpringBoot 开发一个后台程序(还未完成),特写感想记录一下 1. 为什么选择SpringBoot ? 首先是目前很多公司的后台还是J ...

  8. zabbix4.0部署

    1.环境检查 uname -r getenforce systemctl status firewalld.service 2.设置解析,自建yum源(可选) /etc/hosts #!/bin/ba ...

  9. mysql linux下安装部署

    一.安装简介 用户名:mysql安装目录:/usr/local/mysql-5.5数据库目录:/data/mysql/data源码包:mysql-5.5.28.tar.gz 二.安装准备 a.vi / ...

  10. 关系型数据库MySQL(三)_触发器

    简介 用来给保证数据完整性的一种方法,经常用于加强数据的完整性: 是与表事件相关的特殊的存储过程,与存储过程的唯一区别是触发器不能执行execute语句调用,而是在用户执行SQL语句时自动触发执行 执 ...