多路复用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 ...
随机推荐
- UVA.674 Coin Change (DP 完全背包)
UVA.674 Coin Change (DP) 题意分析 有5种硬币, 面值分别为1.5.10.25.50,现在给出金额,问可以用多少种方式组成该面值. 每种硬币的数量是无限的.典型完全背包. 状态 ...
- 一个简单的适用于Vue的下拉刷新,触底加载组件
一个简单的适用于Vue的上拉刷新,触底加载组件,没有发布npm需要时直接粘贴定制修改即可 <template> <div class="list-warp-template ...
- Train-net流程
- [ZJOI2010]排列计数 (组合计数/dp)
[ZJOI2010]排列计数 题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有 ...
- Stars POJ - 2352
Astronomers often examine star maps where stars are represented by points on a plane and each star h ...
- 神经网络CNN训练心得--调参经验
1.样本要随机化,防止大数据淹没小数据 2.样本要做归一化.关于归一化的好处请参考:为何需要归一化处理3.激活函数要视样本输入选择(多层神经网络一般使用relu)4.mini batch很重要,几百是 ...
- uboot下的命令行
1.典型嵌入式linux系统启动过程: 嵌入式系统上电后先执行uboot.然后uboot负责初始化DDR,初始化Flash,然后将OS从Flash中读取到DDR中,然后启动OS(OS启动后uboot就 ...
- [技巧篇]05.关于eclipse模版
<?xml version="1.0" encoding="UTF-8" standalone="no"?><templa ...
- Spring 学习笔记之整合Hibernate
Spring和Hibernate处于不同的层次,Spring关心的是业务逻辑之间的组合关系,Spring提供了对他们的强大的管理能力, 而Hibernate完成了OR的映射,使开发人员不用再去关心SQ ...
- 数据结构:K-D树
K-D树实际上是一棵高维二叉搜索树,与普通二叉搜索树不同的是,树中存储的是一些K维数据 普通的二叉搜索树是一维的,当推广到K维后,就是我们的K-D树了 在K-D树中跟二叉搜索树差不多,也是将一个K维的 ...