Linux 高级I/O之poll函数及简单服务器客户端编程
发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,当需要同时监听多个文件描述符时,就需要I/O复用函数,I/O复用函数有select、poll、epoll,今天主要使用poll函数。poll()接受一个指向结构'struct pollfd'列表的指针
千家信息网最后更新 2025年01月23日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安全错误
数据库的锁怎样保障安全
中文科技期刊数据库期刊查询
azure云服务器免费
迅蓝互联网科技
国家网络安全教育意义
数据库字段的长度比例
服务器文件权限修改
数据库分析原理与应用
乔故网络技术工作室
软件开发编码是每条还是每行
t 数据库修复
达州市网络安全局
一台主机做服务器需要啥配置
东阳市吴宁海宸网络技术服务部
视频录播服务器
手机三国杀服务器
软件开发项目交流记录
gamil邮箱服务器链接失败
嵌入式好还是网络安全
网络安全配置eve是什么
广州募美互联网科技有限公司
杭州传奇游戏软件开发公司
主根服务器什么时候出来的
win10有没有自带数据库
高质量软件开发的案例
网上换服务器麻烦吗
下裁一个服务器
网络安全保密图板
鼓楼区电商app软件开发
小程序服务器管理面板
个人如何做游戏服务器