多路复用I/O模型select() 模型 代码实现
多路复用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() 模型 代码实现的更多相关文章
- linux下多路复用模型之Select模型
Linux关于并发网络分为Apache模型(Process per Connection (进程连接) ) 和TPC , 还有select模型,以及poll模型(一般是Epoll模型) Select模 ...
- select模型
在Windows中所有的socket函数都是阻塞类型的,也就是说只有网络中有特定的事件发生时才会返回,在没有发生事件时会一直等待,虽说我们将它们设置为非阻塞状态,但是在对于服务器段而言,肯定会一直等待 ...
- Linux网络通信编程(套接字模型TCP\UDP与IO多路复用模型select\poll\epoll)
Linux下测试代码: http://www.linuxhowtos.org/C_C++/socket.htm TCP模型 //TCPClient.c #include<string.h> ...
- 多路复用I/O模型poll() 模型 代码实现
多路复用I/O模型poll() 模型 代码实现 poll()机制和select()机制是相似的,都是对多个描述符进行轮询的方式. 不同的是poll()没有描述符数目的限制. 是通过struct pol ...
- python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...
- 31网络通信之Select模型
多路复用并发模型 -- select #include<sys/select.h> #include<sys/time.h> int select(int maxfd, f ...
- (IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
参考博客: https://www.cnblogs.com/xiao987334176/p/9056511.html 内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yi ...
- IO模型之AIO代码及其实践详解
一.AIO简介 AIO是java中IO模型的一种,作为NIO的改进和增强随JDK1.7版本更新被集成在JDK的nio包中,因此AIO也被称作是NIO2.0.区别于传统的BIO(Blocking IO, ...
- 关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记.
说明 为何要写这篇文章 ,之前看过阿二的梦想船的<Poco::TCPServer框架解析> http://www.cppblog.com/richbirdandy/archive/2010 ...
随机推荐
- BZOJ1565:[NOI2009]植物大战僵尸——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=1565 https://www.luogu.org/problemnew/show/P2805 Pla ...
- POJ.1061 青蛙的约会 (拓展欧几里得)
POJ.1061 青蛙的约会 (拓展欧几里得) 题意分析 我们设两只小青蛙每只都跳了X次,由于他们相遇,可以得出他们同余,则有: 代码总览 #include <iostream> #inc ...
- bzoj4321: queue2(DP)
woc万能的OEIS大法!这题居然是有递推式的QAQ http://oeis.org/A002464 这题的状态想不出来T^T... f[i][j][0/1]表示前i个编号,有j对相邻的编号位置上相邻 ...
- X day4
题目 官方题解 T1: 单调栈,单调队列因为认为考场上会写崩所以写了一个十分暴力的方法(线段树) 然后做一做区间覆盖即可 #include<iostream> #include<cs ...
- NYOJ 740 DP
“炫舞家“ST 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 ST是一个酷爱炫舞的玩家.TA很喜欢玩QQ炫舞,因此TA也爱屋及乌的喜欢玩跳舞机(Dance Danc ...
- Web前端工程师-优秀简历汇总
Web前端工程师-优秀简历汇总 1. http://www.linqing07.com/resume.html 2. http://www.flqin.com/#page2 3. ht ...
- js script type 部分属性值分析
1. text/javascript: (1)<script type="text/javascript" src="Js/jquery-1.10.2.min.js ...
- 利用pdfJS实现以读取文件流方式在线展示pdf文件
第一步:下载源码https://github.com/mozilla/pdf.js 第二步:构建PDF.js 第三步:修改viewer.js var DEFAULT_URL = 'compressed ...
- MongoDB入门(5)- 我们自己封装的MongoDB-Java版本
用法 实体定义 package com.wisdombud.mongotool; import java.io.Serializable; import java.util.Date; import ...
- DBA操作常用命令
一.ORACLE的启动和关闭 1.在单机环境下 要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 su - oracle a.启动ORACLE系统 orac ...