1、相关接口介绍

1.1 select

----------------------------------------------------------------------

#include <sys/select.h>

#include <sys/time.h>

int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);

返回:准备好描述字的正数目,0—超时,-1—出错。

----------------------------------------------------------------------

参数说明:

maxfdp1: 制定要检查的描述符的个数,实际应用中传入最大描述符加1,表明要检查0到最大描述符中间的所有描述符。

readset、writeset、exceptset: 这三个参数都是值-结果参数,传入的是应用程序想让内核检查的套接字集合,传出的是内核检查过的可进行操作的套接字集合。

timeout: 超时设置,NULL表示一直等,直到有一个套接字准备好I/O时才返回,将秒和微秒两个字段都设置为0表示不等待,立即返回。

1.2 fd_set

fd_set: 存放套接字的集合。

有四个操作fd_set的宏,分别是:

void FD_ZERO(fd_set *fdset);

void FD_SET(int fd, fd_set *fdset);

void FD_CLR(int fd, fd_set *fdset);

void FD_ISSET(int fd, fd_set *fdset);

FD_SET设置文件描述符集fdset中对应于文件描述符fd的位(设置为1)

FD_CLR清除文件描述符集fdset中对应于文件描述符fd的位(设置为0)

FD_ZERO清除文件描述符集fdset中的所有位(既把所有位都设置为0)。

使用这3个宏在调用select前设置描述符屏蔽位,在调用select后使用FD_ISSET来检测文件描述符集fdset中对应于文件描述符fd的位是否被设置。

1.3 timeval

是一个表示时间的结构体:

 struct timeval
{
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};

2、select I/O复用模型的工作流程

2.1 初始化的时候将要检查的socket放入事先定义好的fd_set集合中;

2.2通过调用select函数来获取可读、可写的socket集合;

2.3 获取集合后先检查监听socket,看是否有新的socket连接,若有,则将新的socket添加到集合中准备下一次的扫描;

2.4扫描检查过的集合,对相应的socket进行读写操作;

以下是一个使用select的简单demo,可以处理多个客户端同时跟服务端通信。

3、一个简单的Echo Server

 #include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h> #define PORT 8080
#define LISTENQ 5
#define MAXLINE 1024
#define IS_ERROR(condition) \
if(condition) \
{ \
printf("Error in func[%s] and line[%d]!\n", \
__PRETTY_FUNCTION__, __LINE__); \
return ; \
} int main(int argc, char *argv[])
{
struct sockaddr_in addrSer;
struct sockaddr_in addrCli;
int listenSock;
int connSock;
int clientSock[FD_SETSIZE]; int maxSock; //the max fd
int sumSock; //sum of client sockets - 1
int nCliLen; //len of addrCli
int nReady; //the num of ready sockets fd_set allset;
fd_set rset; char buf[MAXLINE];
int nRet;
int i; /*create listen socket*/
listenSock = socket(AF_INET, SOCK_STREAM, );
IS_ERROR(listenSock == -); /*bind listen port*/
bzero(&addrSer, sizeof(addrSer));
addrSer.sin_family = AF_INET;
addrSer.sin_addr.s_addr = htonl(INADDR_ANY);
addrSer.sin_port = htons(PORT);
nRet = bind(
listenSock,
(struct sockaddr *)&addrSer,
sizeof(struct sockaddr_in)
);
IS_ERROR(nRet == -); /*listen port*/
nRet = listen(listenSock, LISTENQ);
IS_ERROR(nRet == -); /*init*/
maxSock = listenSock;
sumSock = -; /*Init socket array*/
for (i=; i<FD_SETSIZE; ++i)
{
clientSock[i] = -;
} /*Init fd_set*/
FD_ZERO(&allset);
FD_SET(listenSock, &allset); /*request*/
while ()
{
rset = allset;
nReady = select(maxSock+, &rset, NULL, NULL, NULL); /*accept*/
if (FD_ISSET(listenSock, &rset))
{
nCliLen = sizeof(addrCli);
connSock = accept(listenSock, (struct sockaddr *)&addrCli, &nCliLen);
for (i=; i<FD_SETSIZE; ++i)
{
if (clientSock[i] < )
{
clientSock[i] = connSock;
break;
}
} if (i == FD_SETSIZE)
{
printf("too many clients!\n");
return ;
} FD_SET(connSock, &allset); maxSock = (maxSock < connSock) ? connSock : maxSock;
sumSock = (sumSock < i) ? i : sumSock; if (--nReady <= )
{
continue;
}
} /*send and recv*/
for (i=; i<=sumSock; ++i)
{
if (clientSock[i] < )
{
continue;
} if (FD_ISSET(clientSock[i], &rset))
{
nRet = recv(clientSock[i], buf, MAXLINE, ); if (nRet == || nRet == -)
{
printf("read sock %d err, nRet = %d!\n", clientSock[i], nRet);
close(clientSock[i]);
FD_CLR(clientSock[i], &allset);
clientSock[i] = -;
}
else if (- == send(clientSock[i], buf, nRet, ))
{
printf("write sock %d err!\n", clientSock[i]);
close(clientSock[i]);
FD_CLR(clientSock[i], &allset);
clientSock[i] = -;
} if (--nReady <= )
{
break;
}
} //if (FD_ISSET(clientSock[i], &rset))
} //for (i=0; i<=sumSock; ++i)
} //while(1) return ;
}

UNIX网络编程-Select模型学习的更多相关文章

  1. UNIX网络编程-Poll模型学习

    1.相关接口介绍 1.1 poll ---------------------------------------------------------------------- #include &l ...

  2. UNIX网络编程——select函数的并发限制和 poll 函数应用举例

    一.用select实现的并发服务器,能达到的并发数,受两方面限制 1.一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n来调整或者使用setrlimit函数设置,  ...

  3. UNIX网络编程——网络I/O模型

    在学习UNIX网络编程的时候.一開始分不清 同步 和 异步,所以还是总结一下,理清下他们的差别比較好. IO分类 IO依据对IO的调度方式可分为堵塞IO.非堵塞IO.IO复用.信号驱动IO.异步IO. ...

  4. 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

    本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...

  5. UNIX网络编程——使用select函数编写客户端和服务器

    首先看原先<UNIX网络编程--并发服务器(TCP)>的代码,服务器代码serv.c: #include<stdio.h> #include<sys/types.h> ...

  6. Unix网络编程中的五种I/O模型_转

    转自:Unix网络编程中的的五种I/O模型 下面主要是把unp第六章介绍的五种I/O模型. 1. 阻塞I/O模型 例如UDP函数recvfrom的内核到应用层.应用层到内核的调用过程是这样的:首先把描 ...

  7. 《UNIX网络编程 卷1》之"学习环境搭建"(CentOS 7)

    <UNIX网络编程 卷1>的源码可以从www.unpbook.com下载得到.解压之后的目录为unpv13e. 详细步骤 编译 进入unpv13e目录,按如下步骤编译: ./configu ...

  8. UNIX网络编程 第6章 I/O复用:select和poll函数

    UNIX网络编程 第6章 I/O复用:select和poll函数

  9. 记录一次配置unix网络编程环境的过程和遇到的问题

    记录一次搭建unix网络编程环境过程中遇到的问题和总结 计算机环境虚拟机 linuxmint-18-xfce-64bit 1.打开unix网络编程.iso 把目录下的文件复制到某一目录,修改权限,可命 ...

随机推荐

  1. GWAS Simulation

    comvert hmp to ped1, ped2, map fileSB1.ped, SB2.ped, SB.map 1, choose 20 markers for 30 times(WD: /s ...

  2. VS2010调试C程序,总是一闪而过

    今天在vs2010调试C语言程序的时候,一闪而过,百度上搜了三种解决的方法,都是可以用的. 1.   #include<iostream> using namespace std; int ...

  3. STM3210x建工程库函数版本

    1.首先下载一个固件库,我下载的是stm32f10x_stdperiph_lib 3.5V版的 2.新建一个文件夹,可命名为"STM32建工程库函数版本" 3.在"STM ...

  4. uva1262

    /* 解码 _________________________________________________________________________________ #include < ...

  5. Eclipse动态web工程(Dynamic Web Project)添加jar文件的正确方法

    Eclipse中,创建了动态web工程之后,如果需要添加新的jar文件,有两种方法.第一种是配置工程的“build path”,第二种则是将jar文件放在工程目录下的“/WebContent/WEB- ...

  6. 全面解析sizeof(下) 分类: C/C++ StudyNotes 2015-06-15 10:45 263人阅读 评论(0) 收藏

    以下代码使用平台是Windows7 64bits+VS2012. sizeof作用于基本数据类型,在特定的平台和特定的编译中,结果是确定的,如果使用sizeof计算构造类型:结构体.联合体和类的大小时 ...

  7. 【PKU1001】Exponentiation(高精度乘法)

    Exponentiation Time Limit: 500MS   Memory Limit: 10000K Total Submissions: 145642   Accepted: 35529 ...

  8. (转) Deep Learning Resources

    转自:http://www.jeremydjacksonphd.com/category/deep-learning/ Deep Learning Resources Posted on May 13 ...

  9. 山东省滕州市木石镇化石沟村QQ群116528924

    山东省滕州市木石镇化石沟村QQ群116528924

  10. Yii2 利用controllerMap自定义控制器类

    版权声明:本文为博主原创文章,未经博主允许不得转载. Yii2框架为我们自定义好的  controllers,Models,views,标准的MVC结构框架,但是有些时候我们写接口希望结构更加清晰而不 ...