多路复用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 ...
随机推荐
- BZOJ1041 [HAOI2008]圆上的整点 【数学】
1041: [HAOI2008]圆上的整点 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4631 Solved: 2087 [Submit][S ...
- HDOJ(HDU).2602 Bone Collector (DP 01背包)
HDOJ(HDU).2602 Bone Collector (DP 01背包) 题意分析 01背包的裸题 #include <iostream> #include <cstdio&g ...
- Linux之同步互斥阻塞20160703
主要介绍一下Linux下的互斥与阻塞方面的知识: 1. 原子操作 原子操作指的是在执行过程中不会被别的代码路径所中断的操作. 常用原子操作函数举例: atomic_t v = ATOMIC_INIT( ...
- 题解【luoguP4145 上帝造题的七分钟2(花神游历各国)】
题目链接 题解 题目大意: 一个序列,支持区间开方与求和操作. 算法:线段树实现开方修改与区间求和 分析: 显然,这道题的求和操作可以用线段树来维护 但是如何来实现区间开方呢 大家有没有这样的经历:玩 ...
- pc扫码支付
https://www.cnblogs.com/shengyu-kmust/p/5228261.html https://pay.weixin.qq.com/wiki/doc/api/native.p ...
- [LeetCode] 21. Merge Two Sorted Lists ☆
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...
- ajax 请求数据的两种方法
实现ajax 异步访问网络的方法有两个.第一个是原始的方法,第二个是利用jquery包的 原始的方法不用引入jquery包,只需在html中编写script 片段 这里我演示的是一个传递参数查询的例子 ...
- 杭电多校第八场-A-Character Encoding
题目描述 In computer science, a character is a letter, a digit, a punctuation mark or some other similar ...
- http学习 - 缓存
对缓存的理解更加深刻,缓存有一个过期时间,现在用的比较多的是 max-age,以前使用 expirt之类的, 然后就是需要向服务器验证是否是最新的,如果不是最新的则需要更新.
- Linux修改用户密码
1. root修改自己 # passwd 2. root修改别人 # passwd oracle //修改oracle的密码