Linux网络编程——tcp并发服务器(epoll实现)
https://blog.csdn.net/lianghe_work/article/details/46551871
通过epoll实现tcp并发回执服务器(客户端给服务器发啥,服务器就给客户端回啥)
代码如下:
#include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/select.h> #include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/epoll.h> #include <errno.h> #define OPEN_MAX 100 int main(int argc, char *argv[]) { struct epoll_event event; // 告诉内核要监听什么事件 struct epoll_event wait_event; //内核监听完的结果 //1.创建tcp监听套接字 int sockfd = socket(AF_INET, SOCK_STREAM, 0); //2.绑定sockfd struct sockaddr_in my_addr; bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(8001); my_addr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)); //3.监听listen listen(sockfd, 10); //4.epoll相应参数准备 int fd[OPEN_MAX]; int i = 0, maxi = 0; memset(fd,-1, sizeof(fd)); fd[0] = sockfd; int epfd = epoll_create(10); // 创建一个 epoll 的句柄,参数要大于 0, 没有太大意义 if( -1 == epfd ){ perror ("epoll_create"); return -1; } event.data.fd = sockfd; //监听套接字 event.events = EPOLLIN; // 表示对应的文件描述符可以读 //5.事件注册函数,将监听套接字描述符 sockfd 加入监听事件 int ret = epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event); if(-1 == ret){ perror("epoll_ctl"); return -1; } //6.对已连接的客户端的数据处理 while(1) { // 监视并等待多个文件(标准输入,udp套接字)描述符的属性变化(是否可读) // 没有属性变化,这个函数会阻塞,直到有变化才往下执行,这里没有设置超时 ret = epoll_wait(epfd, &wait_event, maxi+1, -1); //6.1监测sockfd(监听套接字)是否存在连接 if(( sockfd == wait_event.data.fd ) && ( EPOLLIN == wait_event.events & EPOLLIN ) ) { struct sockaddr_in cli_addr; int clilen = sizeof(cli_addr); //6.1.1 从tcp完成连接中提取客户端 int connfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); //6.1.2 将提取到的connfd放入fd数组中,以便下面轮询客户端套接字 for(i=1; i<OPEN_MAX; i++) { if(fd[i] < 0) { fd[i] = connfd; event.data.fd = connfd; //监听套接字 event.events = EPOLLIN; // 表示对应的文件描述符可以读 //6.1.3.事件注册函数,将监听套接字描述符 connfd 加入监听事件 ret = epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &event); if(-1 == ret){ perror("epoll_ctl"); return -1; } break; } } //6.1.4 maxi更新 if(i > maxi) maxi = i; //6.1.5 如果没有就绪的描述符,就继续epoll监测,否则继续向下看 if(--ret <= 0) continue; } //6.2继续响应就绪的描述符 for(i=1; i<=maxi; i++) { if(fd[i] < 0) continue; if(( fd[i] == wait_event.data.fd ) && ( EPOLLIN == wait_event.events & (EPOLLIN|EPOLLERR) )) { int len = 0; char buf[128] = ""; //6.2.1接受客户端数据 if((len = recv(fd[i], buf, sizeof(buf), 0)) < 0) { if(errno == ECONNRESET)//tcp连接超时、RST { close(fd[i]); fd[i] = -1; } else perror("read error:"); } else if(len == 0)//客户端关闭连接 { close(fd[i]); fd[i] = -1; } else//正常接收到服务器的数据 send(fd[i], buf, len, 0); //6.2.2所有的就绪描述符处理完了,就退出当前的for循环,继续poll监测 if(--ret <= 0) break; } } } return 0; }运行结果:
源码下载:
Linux网络编程——tcp并发服务器(epoll实现)相关推荐
- Linux网络编程——tcp并发服务器(poll实现)
https://blog.csdn.net/lianghe_work/article/details/46535859 想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程--I/ ...
- Linux网络编程——tcp并发服务器(多进程)
https://blog.csdn.net/lianghe_work/article/details/46503895 一.tcp并发服务器概述 一个好的服务器,一般都是并发服务器(同一时刻可以响应多 ...
- Linux网络编程——tcp并发服务器(多线程)
https://blog.csdn.net/lianghe_work/article/details/46504243 tcp多线程并发服务器 多线程服务器是对多进程服务器的改进,由于多进程服务器在创 ...
- Linux网络编程——tcp并发服务器(I/O复用之select)
https://blog.csdn.net/lianghe_work/article/details/46519633 与多线程.多进程相比,I/O复用最大的优势是系统开销小,系统不需要建立新的进程或 ...
- Linux网络编程——tcp并发服务器(I/O复用之select
http://blog.csdn.net/lianghe_work/article/details/46519633 与多线程.多进程相比,I/O复用最大的优势是系统开销小,系统不需要建立新的进程或者 ...
- 【Linux网络编程】并发服务器的三种实现模型
服务器设计技术有很多,按使用的协议来分有 TCP 服务器和 UDP 服务器,按处理方式来分有循环服务器和并发服务器. 循环服务器与并发服务器模型 在网络程序里面,一般来说都是许多客户对应一个服务器(多 ...
- linux网络编程之并发服务器的三种实现模型 (超级经典)
转载 : http://blog.csdn.net/tennysonsky/article/details/45671215 服务器设计技术有很多,按使用的协议来分有 TCP 服务器和 UDP 服务器 ...
- 【Linux网络编程】并发服务器之select模型
00. 目录 文章目录 00. 目录 01. 概述 02. I/O复用技术概述 03. select模型服务器实现思路 04. select模型服务器实现 05. 附录 01. 概述 服务器设计技术有 ...
- 【Linux网络编程】并发服务器之多线程模型
00. 目录 文章目录 00. 目录 01. 概述 02. 多线程服务器 03. 多线程服务器实现思路 04. 多线程服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按使用的协议来分有 ...
最新文章
- python零基础实例-Python初学零基础也不怕,从0开始!
- 我国法定报告的传染病分为几类?包括哪些传染病?
- ZCMU 1958: 机器翻译(技巧性的模拟)
- 1033 旧键盘打字 (20 分)(c语言)
- [转]Java常用概念解答
- mysql实现点赞和取消_Redis是如何实现点赞、取消点赞的?
- 多智能体强化学习算法【三】【QMIX、MADDPG、MAPPO】
- 【转】乱码翻译全攻略
- gigabyte计算机主板图解,技嘉主板BIOS如何设置及进入 技嘉主板BIOS设置图解教程(2)...
- R语言绘制列线图nomogram分步骤从头到尾实战
- 基于MS强度或计数的数据依赖法非标记定量蛋白质组学的蛋白质互作分析(一)
- MPS | 聊聊功率因数校正那些事儿
- 软件工程方法论对我们经软件开发有多大用处?
- 客户体验和营销:您需要了解的 5 个最佳实践
- 每天学点统计学——频率和累计频数
- 使用husky配置git代码提交规范
- 微库:微信互动管理平台
- 配水果蜜桔/蜜橘的朋友圈文案,蜜桔/蜜橘水果宣传文案模版
- 基于Multisim的4*4 乘法器原理图设计和仿真
- Analyzer脑电数据处理步骤
热门文章
- 将训练集构建成ImageNet模型
- perl exe执行提示缺少文件解决方法
- Spring Boot系列教程一:Eclipse安装spring-tool-suite插件
- 字符串分割与存入List集合
- $Android自定义控件在不同状态下的属性
- Standard C++ Episode 7
- 小心pthread_cond_signal和SetEvent之间的差异
- android git上传出现错误,热更新上传patch包时提示上传失败,文件不合法
- jsp 上传转码_最完整的处理jsp处理乱码问题步骤,不需要手工转码
- mysql字段唯一确定_验证表里某不确定的字段的值是否唯一的方法?