unix下网络编程之I/O复用(四)
首先需要了解的是select函数:
select函数
#include<sys/select.h>
#include<sys/time.h>
int select (int maxfd , fd_set *readset ,fd_set *writeset, fd_set *exceptionset , const struct timeval * timeout);
返回:就绪描述字的正数目,0——超时,-1——出错
参数解释:
maxfd: 最大的文件描述符(其值应该为最大的文件描述符字 + 1)
readset: 内核读操作的描述符字集合
writeset:内核写操作的描述符字集合
exceptionset:内核异常操作的描述符字集合
timeout:等待描述符就绪需要多少时间。NULL代表永远等下去,一个固定值代表等待固定时间,0代表根本不等待,检查描述字之后立即返回。
注意:readset,writeset,exceptionset都是值-结果参数,意思就是他们传进入指针进去,函数根据指针可以修改对应的fd_set
fd_set集合操作
fd_set和名字一样,是一个描述符的集合。有下面几个操作:
void FD_ZERO(fd_set *fdset); /* 将所有fd清零 */
void FD_SET(int fd, fd_set *fdset); /* 增加一个fd */
void FD_CLR(int fd, fd_set *fdset); /* 删除一个fd */
int FD_ISSET(int fd, fd_set *fdset); /* 判断一个fd是否有设置 */
我们现在要做一个select使用的server,server监听两个端口(7778和7779)的socket。再使用两个cli,一个client连接到7778端口,另一个client连接到7779端口。
服务器端代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#include <unistd.h>int main(int argc, char *argv[]){ //这个服务器同时监听7777和7778两个端口 //绑定监听7779端口的fd int listenfd1; struct sockaddr_in serv_addr1; listenfd1 = socket(AF_INET, SOCK_STREAM, 0); bzero((char *) &serv_addr1, sizeof(serv_addr1)); serv_addr1.sin_family = AF_INET; serv_addr1.sin_port = htons(7777); serv_addr1.sin_addr.s_addr = INADDR_ANY; bind(listenfd1, (struct sockaddr *) &serv_addr1, sizeof(serv_addr1)); listen(listenfd1, 5); //绑定监听7778端口的fd int listenfd2; struct sockaddr_in serv_addr2; listenfd2 = socket(AF_INET, SOCK_STREAM, 0); bzero((char *) &serv_addr2, sizeof(serv_addr2)); serv_addr2.sin_family = AF_INET; serv_addr2.sin_port = htons(7778); serv_addr2.sin_addr.s_addr = INADDR_ANY; bind(listenfd2, (struct sockaddr *) &serv_addr2, sizeof(serv_addr2)); listen(listenfd2, 5); int maxfd; //为什么这里设置两个fd_set?每次select的时候函数会把没有事件发生的描述字清零,所以需要两个集合 fd_set allset, rset; maxfd = listenfd1; if(listenfd2 > maxfd) { maxfd = listenfd2; } FD_ZERO(&allset); FD_SET(listenfd1, &allset); FD_SET(listenfd2, &allset); int clifd, clilen; struct sockaddr_in cli_addr; char buffer[256]; for(;;) { rset = allset; select(maxfd + 1, &rset, NULL, NULL, NULL); //如果是listenfd1 获取消息 if(FD_ISSET(listenfd1, &rset)) { clilen = sizeof(cli_addr); clifd = accept(listenfd1, (struct sockaddr *) &cli_addr, &clilen); bzero(buffer, 256); read(clifd, buffer, 255); printf("Listenfd1 Message is:%s\r\n", buffer); } //如果是listenfd1 获取消息 if(FD_ISSET(listenfd2, &rset)) { clilen = sizeof(cli_addr); clifd = accept(listenfd2, (struct sockaddr *) &cli_addr, &clilen); bzero(buffer, 256); read(clifd, buffer, 255); printf("Listenfd2 Message is:%s\r\n", buffer); } close(clifd); } close(listenfd1); close(listenfd2); return 0;} |
客户端1 代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <string.h>#include <unistd.h>int main(int argc, char* argv[]){ int socketfd, n; socketfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serv_addr; bzero((char *)&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(7778); connect(socketfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)); write(socketfd, "client message", 14); return 0;} |
客户端2代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include <stdio.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <string.h>#include <unistd.h>int main(int argc, char* argv[]){ int socketfd, n; socketfd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serv_addr; bzero((char *)&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(7779); connect(socketfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)); write(socketfd, "client message", 14); return 0;} |
调用步骤:
1 启动服务器端
2 启动客户端1
3 启动客户端2
4 服务器端表
客户端启动:

服务端表现:

这里就是使用select函数对多个socket进行读监听
unix下网络编程之I/O复用(四)的更多相关文章
- unix下网络编程之I/O复用(三)
poll函数 在上文unix下网络编程之I/O复用(二)中已经介绍了select函数的相关使用,本文将介绍另一个常用的I/O复用函数poll.poll提供的功能与select类似,不过在处理流设备时, ...
- unix下网络编程之I/O复用(一)
什么是I/O复用? What we need is the capability to tell the kernel that we want to be notified if one or mo ...
- unix下网络编程之I/O复用(五)
前言 本章节是用基本的Linux/Unix基本函数加上select调用编写一个完整的服务器和客户端例子,可在Linux(ubuntu)和Unix(freebsd)上运行,客户端和服务端的功能如下: 客 ...
- unix下网络编程之I/O复用(二)
select函数 该函数允许进程指示内核等待多个事件中的任何一个发生,并仅在有一个或是多个事件发生或经历一段指定的时间后才唤醒它.我们调用select告知内核对哪些描述字(就读.写或异常条件)感兴趣以 ...
- TCP/IP网络编程之I/O复用
基于I/O复用的服务端 在前面章节的学习中,我们看到了当有新的客户端请求时,服务端进程会创建一个子进程,用于处理和客户端的连接和处理客户端的请求.这是一种并发处理客户端请求的方案,但并不是一个很好的方 ...
- linux网络编程之socket编程(十四)
经过令国鸡冻的APEC会之后,北京的冬天终于不冷了,有暖气的日子就是倍儿爽呀~~洗完热水澡,舒服的躺在床上欢乐地敲打着键盘,是件多么幸福的事呀,好了,抒发情感后,正题继续. 上节中已经初步学习了UDP ...
- python3网络编程之socketserver
本节主要是讲解python3网络编程之socketserver,在上一节中我们讲到了socket.由于socket无法支持多用户和多并发,于是就有了socket server. socket serv ...
- GO语言的进阶之路-网络编程之socket
GO语言的进阶之路-网络编程之socket 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是socket; 在说socket之前,我们要对两个概念要有所了解,就是IP和端口 ...
- 网络编程之socket
网络编程之socket socket:在网络编程中的一个基本组件,也称套接字. 一个套接字就是socket模块中的socket类的一个实例. 套接字包括两个: 服务器套接字和客户机套接字 套接字的实例 ...
随机推荐
- PHP 最大化资源配置 Resource Limits 错误两则
报错信息1:PHP Fatal error: Allowed memory size of 25165824 bytes exhausted (tried to allocate 67108888 b ...
- package.json字段简要解析
name 必填 应用名称 version 必填 应用版本 description 选填 应用描述,多用于搜索,在npm search 时可以用到 keywords 选填 应用关键字,也多用于搜索 sc ...
- JQuery 操作 iframe
JQuery访问iframe内的元素 $("iframe#Main", top.document).contents().find("#id"); JQuery ...
- 2.mysql高级查询
01.SQL高级查询_排序 1.排序语句:order by 排序字段名 asc(默认的-升序) / desc(降序); 2.例如:查询所有服装类商品,将查询结果以价格升序排序: ...
- 软件体系结构C2风格
首先C2风格是最常用的一种软件体系结构风格.(下图为一个C2风格的架构图) C2是一种基于构件和消息的架构风格,可用于创建灵活的.可伸缩的软件系统.一个C2构架可以看成是按照一定规则由连接件连接的许多 ...
- 汇编笔记 CALL(1)
assume cs:code code segment start: mov ax, ;将AX通用寄存器设0 call s inc ax s: pop ax ;将数据从桟中取出 code ends e ...
- QT QMimeData类
http://blog.csdn.net/xie376450483/article/details/5863810 QMimeData类提为数据提供一个容器,用来记录关于MIME类型数据的信息 QMi ...
- js中介者模式
中介者模式(Mediator),用一个中介者对象来封装一系列对象交互.中介者使各对象不需要显示地相互引用,从而使其松散,而且可以独立地改变它们之间的交互. 从生活中例子自然知道,中介者模式设计两个具体 ...
- java笔试面试(转载)
Java面试笔试题大汇总(最全+详细答案) 2016-02-01 15:23 13480人阅读 评论(8) 收藏 举报 分类: Java面试题(1) 声明:有人说, 有些面试题很变态,个人认为其实 ...
- web自动化:DOM对象
一. 什么是DOM对象 定义:DOM(Document Object Mode,文档对象模型)是一套web标准,定义了访问HTML文档的一套属性.方法和事件 本质:网页与脚本语言沟通的桥梁.脚本语言通 ...