Linux 高级I/O之poll函数及简单服务器客户端编程
发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,当需要同时监听多个文件描述符时,就需要I/O复用函数,I/O复用函数有select、poll、epoll,今天主要使用poll函数。poll()接受一个指向结构'struct pollfd'列表的指针
千家信息网最后更新 2025年12月01日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安全错误
数据库的锁怎样保障安全
彩票系统软件开发 福州
flash 软件开发
osc网络安全
达梦数据库sql关键词转译
四川软件开发技术
普陀区质量软件开发优化价格
大连网络安全公司
全球服务器枪战游戏
云主机服务器的优势
ip地址访问服务器
佛山分布式服务器行情
软件开发进中建好吗
网络安全及舆情知识测试题
互联网公司网络安全分级
西青区数据网络技术诚信合作
怎么查看服务器管理口地址
网络安全攻防大赛方案豆丁
stm32移植 数据库
对网络安全没有影响的是什么
beego 多个数据库
正在初始化数据库
软件公司服务器
望奎软件开发项目管理
诸城软件开发
标准组态软件开发
网络技术和电气自动化
新页软件重装连接数据库
git登录linux服务器命令
中国网络安全绘画
平谷区信息化软件开发优势