Linux 高级I/O之poll函数及简单服务器客户端编程
发表于:2025-02-24 作者:千家信息网编辑
千家信息网最后更新 2025年02月24日,当需要同时监听多个文件描述符时,就需要I/O复用函数,I/O复用函数有select、poll、epoll,今天主要使用poll函数。poll()接受一个指向结构'struct pollfd'列表的指针
千家信息网最后更新 2025年02月24日Linux 高级I/O之poll函数及简单服务器客户端编程
当需要同时监听多个文件描述符时,就需要I/O复用函数,I/O复用函数有select、poll、epoll,今天主要使用poll函数。
poll()接受一个指向结构'struct pollfd'列表的指针,其中包括了你想测试的文件描述符和事件。事件由一个在结构中事件域的比特掩码确定。当前的结构在调用后将被填写并在事件发生后返回。
函数原型:
#includeint poll(struct pollfd *fds, nfds_t nfds, int timeout);struct pollfd{ int fd; /*file descriptor*/ short events; /*requested events*/ short revents; /*returned events*/}
函数参数:fds是要监听的fd的数组,nfds是数组个数,timeout 超时时间 -1是阻塞;
函数说用:通过传入的events的类型去判断返回的类型是否一致,如果一致就该干事了。
events:
常量 | 说明 |
POLLIN | 普通或优先级带数据可读 |
POLLRDNORM | 普通数据可读 |
POLLRDBAND | 优先级带数据可读 |
POLLPRI | 高优先级数据可读 |
POLLOUT | 普通数据可写 |
POLLWRNORM | 普通数据可写 |
POLLWRBAND | 优先级带数据可写 |
POLLERR | 发生错误 |
POLLHUP | 发生挂起 |
POLLNVAL | 描述字不是一个打开的文件 |
接下来是是一个服务器监听两个socket的例子:
服务器代码:
#include#include #include #include #include #include #include #include #include #include #define MAX_POLLFD_NUM 2//#define SERVER_CONN_IP1 "1.1.1.1"//#define SERVER_CONN_IP2 "1.1.1.1"#define DEFAULT_PORT 8000#define BUFF_MAX 1024typedef void(*Server_Rrocess_Thread_Fun)(void *arg);/*thread process function define */typedef struct sever_thread_fun{ Server_Rrocess_Thread_Fun Server_Process_Client_Conn1; Server_Rrocess_Thread_Fun Server_Process_Client_Conn2;}Poll_Server_Process_Clinet_FUN_t;/*connect 1 thread function*/void *Poll_Conn1_Process(void *arg){ unsigned char ucBufArr[BUFF_MAX] = {0}; unsigned long ulSize = 0; int connect_fd ; printf("come pthread conn1 fun to proess conn1\n"); if( (connect_fd = accept( *(int*)arg, (struct sockaddr*)NULL, NULL)) == -1){ printf("accept socket error: %s(errno: %d)",strerror(errno),errno); } ulSize = recv(connect_fd, ucBufArr, BUFF_MAX, 0); if(send(connect_fd, "Hello,you are connected 1!\n", 26,0) == -1) perror("send error"); ucBufArr[ulSize] = '\0'; //sleep(20); printf("recv msg from client: %s\n", ucBufArr); close(connect_fd); pthread_exit((void*)1);}/*connect 1 thread function*/void *Poll_Conn2_Process(void *arg){ unsigned char ucBufArr[BUFF_MAX] = {0}; unsigned long ulSize = 0; int connect_fd ; printf("come pthread conn2 fun to proess conn2\n"); if( (connect_fd = accept( *(int*)arg, (struct sockaddr*)NULL, NULL)) == -1){ printf("accept socket error: %s(errno: %d)",strerror(errno),errno); } ulSize = recv(connect_fd, ucBufArr, BUFF_MAX, 0); if(send(connect_fd, "Hello,you are connected 2!\n", 26,0) == -1) perror("send error"); ucBufArr[ulSize] = '\0'; // sleep(20); printf("recv msg from client: %s\n", ucBufArr); close(connect_fd); pthread_exit((void*)2);}int main(){ int poll_ret = 0; pthread_t thread_conn1; pthread_t thread_conn2; /*socket var*/ int server_socket_fd_conn1; int server_socket_fd_conn2; struct sockaddr_in servaddr_conn1; struct sockaddr_in serveraddr_conn2; /*poll var*/ struct pollfd pollfd_arr[MAX_POLLFD_NUM]; /*init thread fun*/ Poll_Server_Process_Clinet_FUN_t server_conn_handel; server_conn_handel.Server_Process_Client_Conn1 = Poll_Conn1_Process; server_conn_handel.Server_Process_Client_Conn2 = Poll_Conn2_Process; /*create two server socket*/ if( (server_socket_fd_conn1 = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){ printf("create socket conn1 error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } if( (server_socket_fd_conn2 = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){ printf("create socket conn2 error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } /*init socket 1 for conn1*/ memset(&servaddr_conn1, 0, sizeof(servaddr_conn1)); servaddr_conn1.sin_family = AF_INET; servaddr_conn1.sin_addr.s_addr = htonl(INADDR_ANY); servaddr_conn1.sin_port = htons(DEFAULT_PORT); // if( inet_pton(AF_INET, SERVER_CONN_IP1, &servaddr_conn1.sin_addr.s_addr) <= 0){ // printf("inet_pton error for %s\n",SERVER_CONN_IP1); // exit(0); // } /*init socket 2 for conn2*/ memset(&serveraddr_conn2, 0, sizeof(serveraddr_conn2)); serveraddr_conn2.sin_family = AF_INET; serveraddr_conn2.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr_conn2.sin_port = htons(DEFAULT_PORT+1); // if( inet_pton(AF_INET, SERVER_CONN_IP2, &serveraddr_conn2.sin_addr.s_addr) <= 0){ // printf("inet_pton error for %s\n",SERVER_CONN_IP2); // exit(0); // } /*bind connect 1 socket*/ if( bind(server_socket_fd_conn1, (struct sockaddr*)&servaddr_conn1, sizeof(servaddr_conn1)) == -1){ printf("bind socket error1: %s(errno: %d)\n",strerror(errno),errno); exit(0); } /*bind connect 2 socket*/ if( bind(server_socket_fd_conn2, (struct sockaddr*)&serveraddr_conn2, sizeof(serveraddr_conn2)) == -1){ printf("bind socket error2: %s(errno: %d)\n",strerror(errno),errno); exit(0); } /*listen connect 1*/ if( listen(server_socket_fd_conn1, 10) == -1){ printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } /*listen connect 2*/ if( listen(server_socket_fd_conn2, 10) == -1){ printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } pollfd_arr[0].events = POLLRDNORM;/*only read event*/ pollfd_arr[0].fd = server_socket_fd_conn1; pollfd_arr[1].events = POLLRDNORM;/*only read event*/ pollfd_arr[1].fd = server_socket_fd_conn2; while(1) { poll_ret = poll( pollfd_arr, MAX_POLLFD_NUM,-1); if( pollfd_arr[0].revents & POLLRDNORM ) { /*connect 1 process task*/ pthread_create( &thread_conn1, NULL, server_conn_handel.Server_Process_Client_Conn1, (void *)(&pollfd_arr[0].fd)); } if( pollfd_arr[1].revents & POLLRDNORM ) { /*connect 2 process task*/ pthread_create( &thread_conn2, NULL, server_conn_handel.Server_Process_Client_Conn2, (void *)(&pollfd_arr[1].fd)); } sleep(1); } return 0;}
客户端代码:
#include#include #include #include #include #include #include #define BUFF_MAX 1024#define DEFAULT_PORT 8000int main(int argc, char** argv) { int sockfd, n,rec_len; char recvline[BUFF_MAX], sendline[BUFF_MAX]; char buf[BUFF_MAX]; struct sockaddr_in servaddr; if( argc != 2){ printf("usage: ./client \n"); exit(0); } /*create socket*/ if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("create socket error: %s(errno: %d)\n", strerror(errno),errno); exit(0); } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(DEFAULT_PORT/*+1/);/*DEFAULT_PORT is connect 1 to server,DEFAULT_PORT+1 is connect 2 to server*/ /*string ip to int ip*/ if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){ printf("inet_pton error for %s\n",argv[1]); exit(0); } /*connect server*/ if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){ printf("connect error: %s(errno: %d)\n",strerror(errno),errno); exit(0); } printf("send msg to server: \n"); fgets(sendline, BUFF_MAX, stdin); /*write data to sockfd*/ if( send(sockfd, sendline, strlen(sendline), 0) < 0) { printf("send msg error: %s(errno: %d)\n", strerror(errno), errno); exit(0); } /*read socket data*/ if((rec_len = recv(sockfd, buf, BUFF_MAX,0)) == -1) { perror("recv error"); exit(1); } buf[rec_len] = '\0'; printf("Received : %s \n",buf); /*colse socket*/ close(sockfd); exit(0); }
解释:服务器端监听 ip 127.0.0.1 port 8000和ip 127.0.0.1 port 8001
结果演示:
数据
函数
普通
事件
优先级
监听
服务器
服务
文件
结构
一致
代码
数组
类型
复用
客户
客户端
接下来
两个
个数
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
网络数据库应用技术难吗
学校网络技术员的工资待遇
登陆云服务器的视频怎么下载
徐州app软件开发培训
怎么打开游戏服务器
网络安全科普教育的探索与实践
数据库表连接取值范围
万维数据库期末题库
南通万千网络技术有限责任公司
网络安全什么是靶场
数据库基本表实验报告总结
游戏王md无法连接服务器
杭州大虫互联网科技有限公司
mysql推荐数据库
网络安全执法检查总结6
网络安全监督工作方案
合肥软件开发学
武汉帮帮手软件开发有限公司
上海琴策网络技术有限公司
云服务器安装大型游戏
福建网吧网络安全
软件开发项目的目标责任书
职高网络技术需要买电脑吗
网络安全和信息安全区别
网络安全政策和措施
网络安全宣传册下载
excel怎么做论文数据库
服务器负载统计
梦想曙光服务器下载
花生壳弄游戏服务器需要买流量不