多路复用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 ...
随机推荐
- mybatis的Mapper代理原理
前言:在mybatis的使用中,我们会习惯采用XXMapper.java+XXMapper.xml(两个文件的名字必须保持一致)的模式来开发dao层,那么问题来了,在XXMapper的文件里只有接口, ...
- Uva-oj Palindromes 暴力
Palindromes Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Statu ...
- Codeforces Round #311 (Div. 2)B. Pasha and Tea二分
B. Pasha and Tea time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
- tomcat log4j配置
tomcat默认的log使用的是java.util.logging,配置文件在${catalina_base}/conf/logging.properties tomcat日志分类, 1.access ...
- DOM通过ID或NAME获取值
DOM通过ID或NAME获取值 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> &l ...
- 解决oracle数据库 ora-00054:resource busy and acquire with NOWAIT specified 错误
解决oracle数据库 ora-00054:resource busy and acquire with NOWAIT specified 错误 本人在使用pl/sql developer 客户端调用 ...
- 【java】AES加密解密|及Base64的使用
转载自:http://www.cnblogs.com/arix04/archive/2009/10/15/1511839.html AES加解密算法,使用Base64做转码以及辅助加密: packag ...
- 增强学习Reinforcement Learning经典算法梳理3:TD方法
转自:http://blog.csdn.net/songrotek/article/details/51382759 博客地址:http://blog.csdn.net/songrotek/artic ...
- 【C++ STL】Vector
1.结构 vector模塑出一个动态数组,因此,它本身是“将元素置于动态数组中加以管理”的一个抽象概念.vector将其元素复制到内部的dynamic array中.元素之间总存在某种顺序,所以vec ...
- [Luogu 4092] HEOI/TJOI2016 树
[Luogu 4092] HEOI/TJOI2016 树 搜了树剖标签不知道怎么就跳出了个暴搜题啊! 管他既然做了就发上来吧- 有修改标签就向下搜并修改,遇到标签即停止. 这题是真的真的短. #inc ...