一、描述符就绪条件

对于引起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. python使用bs4爬取boss静态页面

    思路: 1.将需要查询城市列表,通过城市接口转换成相应的code码 2.遍历城市.职位生成url 3.通过url获取列表页面信息,遍历列表页面信息 4.再根据列表页面信息的job_link获取详情页面 ...

  2. springboot2集成pagehelper

    springboot2集成pagehelper超级简单,本示例直接抄袭官方示例,仅将数据库由H2改成MySQL而已. 1. pom.xml <?xml version="1.0&quo ...

  3. wamp环境的搭建

    本文详细介绍了在Windows2003下使用Apache2.2.21/PHP5.3.5/Mysql5.5.19/phpMyAdmin3.4.9搭建php开发环境. 第一步:下载安装的文件 1. Apa ...

  4. Pangu and Stones HihoCoder - 1636 区间DP

    Pangu and Stones HihoCoder - 1636 题意 给你\(n\)堆石子,每次只能合成\(x\)堆石子\((x\in[L, R])\),问把所有石子合成一堆的最小花费. 思路 和 ...

  5. python练习题之随机生成验证码

    #引用random模块下的randint项目#定义验证码函数.定义一个空字符串变量,分三种情况,随机产生的大写字母,随机产生的小写字母,随机产生的数字.然后#每一次执行哪一种情况,条件也是随机的,就是 ...

  6. 公司-IT-SanSan:SanSan

    ylbtech-公司-IT-SanSan:SanSan 毫不费力的组织.无缝简单.基于名片的联系人管理 SanSan是一个名片管理应用,为企业提供内部联系人管理和分享服务,此外该公司也是日本最大的.基 ...

  7. ajax请求controller出现中文乱码

    ajax请求controller出现中文乱码 解决方法:在 @RequestMapping 中加上  produces = {"application/json;charset=UTF-8& ...

  8. python 自动把mysql备份文件发送邮箱

    import os import time import sched import smtplib from email.mime.text import MIMEText from email.he ...

  9. “希希敬敬对”队软件工程第九次作业-beta冲刺第五次随笔

    “希希敬敬对”队软件工程第九次作业-beta冲刺第五次随笔 队名:  “希希敬敬对” 龙江腾(队长) 201810775001 杨希                   201810812008 何敬 ...

  10. FastJSON 远程执行漏洞,速速升级!

    相信大家用 FastJSON 的人应该不少,居然有漏洞,还不知道的赶紧往下看,已经知道此漏洞的请略过-- 2019年6月22日,阿里云云盾应急响应中心监测到FastJSON存在0day漏洞,攻击者可以 ...