Linux下socket通信和epoll
上一篇博客用多线程实现服务端和多个客户端的通信,但是在实际应用中如果服务端有高并发的需求,多线程并不是一个好选择。
实现高并发的一种方法是IO多路复用,也就是select,poll,epoll等等。
于是我采用epoll再修改了服务端,实现单线程服务多个客户端。
服务端:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <fcntl.h> // open function 4 #include <unistd.h> // close function 5 #include <sys/socket.h> 6 #include <netinet/in.h> 7 #include <string.h> 8 #include <pthread.h> 9 #include <errno.h> 10 #include <sys/epoll.h> 11 12 const int PORT = 8888; 13 /* 14 listen_loop(): epoll监听套接字,作不同处理 15 accept_conn(): 新的客户端连接进来,执行accept,将fd加入epoll set 16 recv_message(): recv并且重复输出一份给客户端 17 */ 18 void listen_loop(); 19 void accept_conn(unsigned int sock_fd, unsigned int epollfd); 20 void recv_message(unsigned int sock_fd); 21 22 int main(void) { 23 int sock_fd; 24 struct sockaddr_in server_addr; 25 26 //初始化socket 27 sock_fd = socket(AF_INET, SOCK_STREAM, 0); 28 if (sock_fd < 0) { 29 perror("socket:"); 30 return 0; 31 } 32 33 //编辑地址 34 memset(&server_addr, 0, sizeof(server_addr)); 35 server_addr.sin_family = AF_INET;//ipv_4 36 server_addr.sin_port = htons(PORT);//监听端口8888 37 server_addr.sin_addr.s_addr = INADDR_ANY;//本地的任意地址 38 39 //绑定然后监听 40 if (bind(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { 41 perror("bind:"); 42 return 0; 43 } 44 if (listen(sock_fd, 10) < 0) { 45 perror("listen"); 46 return 0; 47 } 48 49 listen_loop(sock_fd); 50 51 return 0; 52 } 53 void accept_conn(unsigned int sock_fd, unsigned int epollfd) { 54 struct sockaddr_in clientaddr; 55 struct epoll_event event; 56 socklen_t len = sizeof(struct sockaddr); 57 int accept_fd = 0; 58 59 accept_fd = accept(sock_fd, (struct sockaddr*)&clientaddr, &len); 60 61 if (accept_fd <= 0) { 62 perror("accept error"); 63 return; 64 } 65 66 //将新建连接加入epoll set 67 event.data.fd = accept_fd; 68 event.events = EPOLLIN | EPOLLET | EPOLLRDHUP; 69 epoll_ctl(epollfd, EPOLL_CTL_ADD, accept_fd, &event); 70 return; 71 } 72 73 void recv_message(unsigned int sock_fd) { 74 char recv_buf[1024], send_buf[1024]; 75 76 memset(recv_buf, 0, sizeof(recv_buf)); 77 memset(send_buf, 0, sizeof(send_buf)); 78 79 recv(sock_fd, recv_buf, sizeof(recv_buf), 0); 80 fputs(recv_buf, stdout); 81 strcpy(send_buf, recv_buf); 82 send(sock_fd, send_buf, sizeof(send_buf), 0); 83 84 return; 85 } 86 void listen_loop(unsigned int sock_fd) 87 { 88 int epollfd, i, ret; 89 int timeout = 300; 90 struct epoll_event event; 91 struct epoll_event eventList[10]; 92 93 /*创建epoll监听事件*/ 94 epollfd = epoll_create(10); 95 event.events = EPOLLIN | EPOLLET; 96 event.data.fd = sock_fd; 97 98 /*注册epoll监听事件.*/ 99 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sock_fd, &event) < 0) { 100 printf("register epoll event err !"); 101 return; 102 } 103 104 while (1) { 105 ret = epoll_wait(epollfd, eventList, 10, timeout); 106 107 /*epoll事件错误.*/ 108 if (ret < 0) { 109 printf("epoll event err!"); 110 break; 111 } 112 /*无事件返回.*/ 113 else if (ret == 0) { 114 continue; 115 } 116 117 /*epoll返回事件.*/ 118 for (i = 0; i < ret; i++) { 119 /*epoll 错误*/ 120 if ((eventList[i].events & EPOLLERR) || (eventList[i].events & EPOLLHUP) || !(eventList[i].events & EPOLLIN)) { 121 printf("epoll error\n"); 122 close(eventList[i].data.fd); 123 exit(-1); 124 } 125 126 //half connection 127 if (eventList[i].events & EPOLLRDHUP) { 128 printf("//one client close the conne.//\n"); 129 close(eventList[i].data.fd); 130 } 131 132 /*accept事件*/ 133 if (eventList[i].data.fd == sock_fd) { 134 accept_conn(sock_fd, epollfd); 135 } 136 /*非sock_fd则为其他事件.*/ 137 else { 138 recv_message(eventList[i].data.fd); 139 } 140 } 141 } 142 close(epollfd); 143 close(sock_fd); 144 return; 145 }
转载于:https://www.cnblogs.com/liangf27/p/9366348.html
Linux下socket通信和epoll相关推荐
- linux下socket编程和epoll的使用
这两天在学Linux下的网络编程,于是便看了些关于socket和epoll的资料. 首先介绍socket,socket编程我之前也接触过,不过是在windows下接触的.和windows不同的 ...
- Linux 下socket通信终极指南(附TCP、UDP完整代码)
linux下用socket通信,有TCP.UDP两种协议,网上的很多教程把两个混在了一起,或者只讲其中一种.现在我把自己这两天研究的成果汇总下来,写了一个完整的,适合初学者参考,也方便自己以后查阅. ...
- Linux下Socket通信中非阻塞connect、select、recv 和 recvfrom、send和sendto大致讲解,附带非租塞connect代码、MSG_NOSIGNAL
linux中send函数MSG_NOSIGNAL异常消息 在服务器端用ctrl+c 来结束服务器接收进程来模拟服务器宕机的情况,结束服务 socket 进程之后,服务端自然关闭进程,可是 client ...
- linux socket ip层配置,Linux下Socket通信(TCP实现)
近期在做的项目中,涉及到了进程间数据传输,系统的原本实现是通过管道,但是原有的实现中两个进程是在同一台机器,而且两个进程的关系为父子关系,而我们要做的是将其中一个进程移植到服务器上,因此两个进程要分开 ...
- linux下socket通信,server和client简单例子
#include "metafile.h" #include <string.h> #include <ctype.h>//定义全局变量 TrackerLi ...
- 【Linux】一篇文章搞定 CPP模拟实现TCP协议下socket通信
CPP模拟实现TCP协议下socket通信 1. TCP 编程流程图 2. 数据收发阶段使用的API 2.1 send接口 2.2 recv接口 3. 两个队列 4. 总结TCP 编程双端流程 5. ...
- linux下TCP通信简单实例
linux下TCP通信简单实例 基于TCP(面向连接)的socket编程,分为服务器端和客户端 服务器端的流程如下: (1)创建套接字(socket) (2)将套接字绑定到一个本地地址和端口上(bin ...
- Linux下进程通信的八种方法
Linux下进程通信的八种方法:管道(pipe),命名管道(FIFO),内存映射(mapped memeory),消息队列(message queue),共享内存(shared memory),信号量 ...
- 【流媒体服务器Mediasoup】 NodeJs与C++信令通信详解及Linux下管道通信的详解(五)
目录 前言 匿名管道进程间通信 进程间管道 的创建与图解 MediaSoup中的管道创建 MediaSoup Channel的创建 NodeJs和 C++ 管道通信的过程 MediaSoup 消息确认 ...
最新文章
- Linux系统JDK安装和配置
- xcode 中无法进行虚拟机调试_在软件部署中使用 strace 进行调试
- 字符串排序 java_java字符串排序
- TJA1050只能RX不能TX
- 盘点Kubernetes网络问题的4种解决方案
- 约束条件创建定义表(主码,外码的确定和防止空值等)
- 打造云上金融!网易云信入选「2021 数字化转型最佳案例 Top10」
- 张正友标定法 【计算机视觉学习笔记--双目视觉几何框架系列】
- 如何实现两列等高效果?
- 【flink】Flink 1.12.2 源码浅析 : yarn-per-job模式解析 JobMasger启动 YarnJobClusterEntrypoint
- paddlepaddle的使用
- Spark-SQL教程
- Ruby在Windows下安装
- Common Digester学习
- Unix时间和leap seconds(闰秒)简要分析
- 听北大公开课庄明科老师《大学生职业素养提升》第一集:《自我效能感》的笔记
- 怎样做一个更有价值的人
- Oracle学习——第四讲(增删改查)
- mysql 查看slave状态_解读show slave status 命令判断MySQL复制同步状态
- 用uni-app开发的微信小程序轮播图----和用微信小程序原生开发的轮播图