多路复用I/O:  socket编程之select(),poll(),epoll()

代码:

client.c

 #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <assert.h>
#define maxn 1100
#define IP "127.0.0.1"
#define PORT 45178
#define MAXLINE 1024
#define LISTENQ 5
#define SIZE 10
#define BACKLOG 2
int main()
{
int sockfd;
if((sockfd = socket(AF_INET,SOCK_STREAM,)) == -)
{
printf("socket error!\n");
exit();
}
struct sockaddr_in server;
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
inet_pton(AF_INET,IP,&server.sin_addr);
char buf[maxn];
int connfd;
connfd = connect(sockfd,(struct sockaddr*)&server,sizeof(server));
if(connfd < )
{
printf("connect failure!\n");
return -;
}
printf("client send to server\n");
printf("please input something\n");
scanf("%s",buf);
write(sockfd,buf,maxn);
char recvbuf[maxn];
char sendbuf[maxn];
fd_set readfd;
int maxnum = ;
struct timeval T_time;
int n;
int sel_fd;
while()
{
FD_ZERO(&readfd);
FD_SET(sockfd,&readfd);
maxnum = sockfd;
T_time.tv_sec = ;
T_time.tv_usec = ;
sel_fd = select(maxnum + ,&readfd,NULL,NULL,&T_time);
if(sel_fd < )
{
continue;
}
else if(sel_fd == -)
{
printf("select error!\n");
return;
}
if(FD_ISSET(sockfd,&readfd))
{
n = read(sockfd,recvbuf,maxn);
if(n <= )
{
printf("server is closed!\n");
close(sockfd);
FD_CLR(sockfd,&readfd);
return;
}
printf("recv message is %s\n", recvbuf);
sleep();
write(sockfd,buf,strlen(buf) + );
}
}
close(sockfd);
return ;
}

server.c

 #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <assert.h>
#define maxn 1100
#define PORT 45178
#define IP "127.0.0.1"
#define MAXLINE 1024
#define LISTENQ 5
#define SIZE 10
#define BACKLOG 2
typedef struct server_context_st
{
int cli_num; /*客户端个数*/
int cli_fds[SIZE]; /*客户端的个数*/
fd_set allfds; /*句柄集合*/
int maxfd; /*句柄最大值*/
} server_context_st; static int init();
static void deal_maxfd(int sockfd);
static int accept_client(int sockfd);
static void recv_client_msg(fd_set *readfd);
static void submit_client_msg(int temp,char buf[]);
static server_context_st *server_client = NULL;
int Max(int a,int b);
int Max(int a,int b)
{
return a>b?a:b;
}
static int server_init()
{
server_client = (server_context_st *)malloc(sizeof(server_context_st));
if(server_client == NULL)
{
return -;
}
memset(server_client,,sizeof(server_context_st));
int i=;
for(;i<SIZE;i++)
{
server_client->cli_fds[i] = -;
}
return ;
}
static int init()
{ int sockfd;
if((sockfd = socket(AF_INET,SOCK_STREAM,)) == -)
{
printf("socket error!\n");
exit();
}
int listenfd;
struct sockaddr_in server;
bzero(&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
inet_pton(AF_INET,IP,&server.sin_addr);
if(bind(sockfd,(struct sockaddr*)&server,sizeof(struct sockaddr)) == -)
{
perror("bind error:");
return -;
}
listen(sockfd,BACKLOG);
return sockfd;
}
static void deal_maxfd(int sockfd)
{
fd_set *readfd = &server_client->allfds;
int sel_fd = ;
int clifd = -;
struct timeval T_time;
while()
{
FD_ZERO(readfd);
FD_SET(sockfd,readfd);
server_client->maxfd = sockfd;
T_time.tv_sec = ;
T_time.tv_usec = ; int i;
for(i=;i<server_client->cli_num;i++)
{
clifd = server_client->cli_fds[i];
FD_SET(clifd,readfd);
server_client->maxfd = Max(clifd,server_client->maxfd);
}
//retval = select(s_srv_ctx->maxfd + 1, readfds, NULL, NULL, &tv);
sel_fd = select(server_client->maxfd+,readfd,NULL,NULL,&T_time);
if(sel_fd == )
{
printf("time out!\n");
continue;
}
else if(sel_fd == -)
{
printf("something error!\n");
return ;
}
if(FD_ISSET(sockfd,readfd))
{
/*监听客户端请求*/
accept_client(sockfd);
}
else
{
/*接受处理客户端消息*/
recv_client_msg(readfd);
}
}
}
static int accept_client(int sockfd)
{
struct sockaddr_in server_c;
socklen_t len;
len = sizeof (server_c);
int afd = -;
Loop:
printf("waiting ............................\n");
afd = accept(sockfd,(struct sockaddr*)&server_c,&len);
if(afd == -)
{
if(errno == EINTR)
{
goto Loop;
}
else
{
fprintf(stderr, "accept fail,error:%s\n", strerror(errno));
return -;
}
}
printf("accept successful!\n");
int i=;
for(i=;i<SIZE;i++)
{
if(server_client->cli_fds[i] < )
{
server_client->cli_fds[i] = afd;
server_client->cli_num ++;
break;
}
}
if(i == SIZE)
{
printf("too many client to accept!\n");
return -;
}
}
static void recv_client_msg(fd_set *readfd)
{
int i=;
int temp;
char buf[maxn];
for(i=;i<server_client->cli_num;i++)
{
temp = server_client->cli_fds[i];
if(temp < )
{
continue;
}
if(FD_ISSET(temp,readfd))
{
int n = read(temp,buf,maxn);
if(n <= )
{
FD_CLR(temp,&server_client->allfds);
close(temp);
server_client->cli_fds[i] = -;
continue;
}
submit_client_msg(temp,buf);
}
}
}
static void submit_client_msg(int temp,char buf[])
{
assert(buf);
printf("receive message is %s\n",buf);
write(temp,buf,strlen(buf)+);
return ;
}
int main()
{
if(server_init() == -)
{
printf("init error\n");
return -;
}
int sockfd;
sockfd = init();
deal_maxfd(sockfd);
close(sockfd);
return ;
}

结果:

多路复用I/O模型select() 模型 代码实现的更多相关文章

  1. linux下多路复用模型之Select模型

    Linux关于并发网络分为Apache模型(Process per Connection (进程连接) ) 和TPC , 还有select模型,以及poll模型(一般是Epoll模型) Select模 ...

  2. select模型

    在Windows中所有的socket函数都是阻塞类型的,也就是说只有网络中有特定的事件发生时才会返回,在没有发生事件时会一直等待,虽说我们将它们设置为非阻塞状态,但是在对于服务器段而言,肯定会一直等待 ...

  3. Linux网络通信编程(套接字模型TCP\UDP与IO多路复用模型select\poll\epoll)

    Linux下测试代码: http://www.linuxhowtos.org/C_C++/socket.htm TCP模型 //TCPClient.c #include<string.h> ...

  4. 多路复用I/O模型poll() 模型 代码实现

    多路复用I/O模型poll() 模型 代码实现 poll()机制和select()机制是相似的,都是对多个描述符进行轮询的方式. 不同的是poll()没有描述符数目的限制. 是通过struct pol ...

  5. python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...

  6. 31网络通信之Select模型

    多路复用并发模型  -- select #include<sys/select.h> #include<sys/time.h> int select(int maxfd,  f ...

  7. (IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    参考博客: https://www.cnblogs.com/xiao987334176/p/9056511.html 内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yi ...

  8. IO模型之AIO代码及其实践详解

    一.AIO简介 AIO是java中IO模型的一种,作为NIO的改进和增强随JDK1.7版本更新被集成在JDK的nio包中,因此AIO也被称作是NIO2.0.区别于传统的BIO(Blocking IO, ...

  9. 关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记.

    说明 为何要写这篇文章 ,之前看过阿二的梦想船的<Poco::TCPServer框架解析> http://www.cppblog.com/richbirdandy/archive/2010 ...

随机推荐

  1. HDOJ.2187 悼念512汶川大地震遇难同胞——老人是真饿了(贪心)

    悼念512汶川大地震遇难同胞--老人是真饿了 点我挑战题目 题目分析 每组数据给出所拥有的钱数,和大米的种类.每种大米给出单价(每单位重量)和大米的重量.求能买到的大米最大重量是多少? 采用贪心算法. ...

  2. 跳跃表 https://61mon.com/index.php/archives/222/

    跳跃表(英文名:Skip List),于 1990 年 William Pugh 发明,是一个可以在有序元素中实现快速查询的数据结构,其插入,查找,删除操作的平均效率都为 . 跳跃表的整体性能可以和二 ...

  3. Codeforces Round #307 (Div. 2) D 矩阵快速幂+快速幂

    D. GukiZ and Binary Operations time limit per test 1 second memory limit per test 256 megabytes inpu ...

  4. 文件上传文件的权限--lnmp 环境配置,尤其整个项目复制过来动~~~

    site_upload  需要是自己才建立动才会是root  root  所有者:---不是root :  root   上传不了文件,不是  777 就都可以上传的,也要看看是谁建立的文件夹: 打包 ...

  5. 转载《mysql 一》:mysql的select查询语句内在逻辑执行顺序

    原文:http://www.jellythink.com/archives/924 我的抱怨 我一个搞应用开发的,非要会数据库,这不是专门的数据库开发人员干的事么?话说,小公司也没有数 据库开发人员这 ...

  6. php中error_reporting

    error_reporting(255);是列出所有提示error_reporting(0);是不显示所有提示建议使用error_reporting(7);只显示严重错误1 E_ERROR 致命的运行 ...

  7. matlab求一个矩阵中各元素出现的个数(归一化)

    function [m,n] = stamatrix(a) %网上找到的方法,感觉很巧妙 x=a(:); x=sort(x); d=diff([x;max(x)+1]); count = diff(f ...

  8. ES6数组的扩展运算符

    一.基本使用 ES6中函数可以使用 rest参数 接收函数的多余参数,组成一个数组,放在形参的最后面. let fn = (a, ...value) => { console.log(a); c ...

  9. 2015/9/10 Python基础(11):错误和异常

    程序在执行的过程中会产生异常,出现错误在以前的一个时期是致命的,后来随着程序的发展,使得一些错误的处理方式是柔和的,发生错误会产生一些错误的诊断信息和一些模糊的提示.帮助我们来处理异常.今天将学习Py ...

  10. [洛谷P1941] 飞扬的小鸟

    洛谷题目链接:飞扬的小鸟 题目描述 Flappy Bird是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了 ...