Linux 高级I/O之poll函数及简单服务器客户端编程
当需要同时监听多个文件描述符时,就需要I/O复用函数,I/O复用函数有select、poll、epoll,今天主要使用poll函数。
poll()接受一个指向结构'struct pollfd'列表的指针,其中包括了你想测试的文件描述符和事件。事件由一个在结构中事件域的比特掩码确定。当前的结构在调用后将被填写并在事件发生后返回。
函数原型:
#include<poll.h>int 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<stdio.h>#include<stdlib.h> #include<string.h> #include<errno.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<pthread.h>#include<unistd.h>#include<poll.h>#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<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #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 <ipaddress>\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
IPLC直译过来是国际私有租赁线路。IPLC产品相对于普通线路的最大优势在于不用担心IP不可用,节省下来更换IP的费用。另外,IPLC专线的成本比较高,相应的延迟时间比较短,速度也比较快。
Linux 高级I/O之poll函数及简单服务器客户端编程相关推荐
- Linux高级字符设备之Poll操作
在用户程序中,select()和poll()也是与设备阻塞与非阻塞访问息息相关的,使用非阻塞I/O的应用程序通常会使用select和poll系统调用查询是否可对设备进行无阻塞的访问.select系统调 ...
- Linux网络编程——I/O复用之poll函数
一.回顾前面的select select优点: 目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点 select缺点: 1.每次调用 select(),都需要把 fd 集合从用户态拷贝到内核 ...
- linux poll函数 实现,Linux select/poll/epoll 原理(一)实现基础
本序列涉及的 Linux 源码都是基于 linux-4.14.143 . 1. 文件抽象 与 poll 操作 1.1 文件抽象 在 Linux 内核里,文件是一个抽象,设备是个文件,网络套接字也是个文 ...
- LINUX下poll函数用法
LINUX下poll函数用法 文章目录 LINUX下poll函数用法 一.函数介绍 二.使用 1. 一.函数介绍 int poll(struct pollfd *fds, nfds_t nfds, i ...
- linux网络编程之多路I/O转接服务器poll函数
(1)poll函数 头文件:#include<poll.h> int poll(struct pollfd*fds, nfds_t nfds,int timeout); struct ...
- linux poll in,Linux poll函数深入理解
poll函数与select函数差不多 函数原型: #include int poll(struct pollfd fd[], nfds_t nfds, int timeout); struct pol ...
- 总结如何从Linux开发工程师到Linux后台开发工程师再到Linux高级互联网架构师
前言: 小编也是从事c方面10多年的工作经验.今天跟大家分享一下我总结出来的一系列 C/C Linux后台服务器开发的学习路线.从Linux开发工程师-Linux后台开发工程师-Linux高级互联网架 ...
- linux web高级编程,寒假学习 第16.17天 (linux 高级编程)
寒假学习 第16.17天 (linux 高级编程) 笔记 总结 一.进程的基本控制(进程的同步) 1.进程的常见控制函数 pause sleep/usleep atexit on_exit i ...
- 《Linux 高级程序设计(第三版)》——导读
** 前言 ** Linux应用开发是目前最为广泛的软件开发内容之一,同时也是从事Linux内核及驱动开发的基础.<Linux高级程序设计>一书经过两次出版,收到了大量的读者来信,对本书提 ...
最新文章
- https://www.exploit-db.com/下载POC比较完善的代码
- 优化缩短关中断的时间
- 【转】arm和x86的区别
- 分支界限算法【0-1背包问题】按照优先队列式(LC)分支限界法求解0-1背包问题, 并给出限界函数,并画出该实例的状态空间树。
- 文献学习(part11)--基于知识图谱的推荐系统研究综述
- 与詹金斯一起将GitLab中的Gradle项目发布到Artifactory
- symbian系统开发教程(一)
- 使用git建立本地仓储管理代码【转】
- C#中文件与文件夹相关的操作
- kep server 6.4 激活_轻松一点,一触屏蔽!5G和未来显示的福音——低压激活,敏感元器件专用保护方案...
- 旧的起点(开园说明)
- python的难点是什么,【python基础学习】基础重点难点知识汇总
- SwipeRefreshLayout+RecyclerView滑动冲突解决
- Qt编程入门(1) : 信号和槽
- 大漠为什么不支持win10_Win10系统注册使用大漠插件的方法与设置!常见错误0x8002801...
- 伪装成mysql的备_如何伪装成一个服务端开发(六) -- 数据库操作
- JavaScript实现公历转换农历
- 被低估的BIRT报表 二 Birt也可以很漂亮
- python 条形图填充疏密_Python数据分析 4:图表绘制工具Matplotlib
- SpringBoot 日志(学习笔记13)
热门文章
- [20160307]绑定变量的分配长度3.txt
- 文件结束[置顶] javaweb框架--自定义标签与freemaker结合
- AE 各分析适用数据
- C++ 设计People类-1
- linux不断安装操作系统,无人值守批量安装linux操作系统
- java安全点_关于OopMap、SafePoint(安全点)以及安全区域
- 最全面的Linux指令大全
- 洛谷P1003 铺地毯 noip2011提高组day1T1
- 《你说对就队》第四次作业:项目需求调研与分析
- button 元素的css3旋转动画