百独托管7500 紫田网络超高转化播放器收cps[推荐]速盾CDN 免实名免备防屏蔽阿里云 爆款特卖9.9元封顶提升alexa、IP流量7Q5团队
【腾讯云】中小企福利专场【腾讯云】多款产品1折起高防 随时退换 好耶数据小飞国外网赚带你月入万元炎黄网络4H4G10M 99每月
香港带宽CN2/美国站群优惠中客数据中心 服务器租用联盟系统移动广告平台 中易企业专场腾讯云服务器2.5折九九数据 工信部正规资质
腾讯云新用户大礼包代金券高价收cpa注册量高价展示【腾讯云】2核2G/9.93起租服务器找45互联 随时退换阿里云 短信服务 验证秒达

Linux 高级I/O之poll函数及简单服务器客户端编程 [复制链接]
查看:160 | 回复:0

779

主题

790

帖子

0

积分

落伍者(一心一意)

Rank: 1

贡献
961
鲜花
0
注册时间
2021-2-24

落伍手机绑定

发表于 2021-8-3 10:15:15 | 显示全部楼层 |阅读模式 来自 中国北京

当需要同时监听多个文件描述符时,就需要I/O复用函数,I/O复用函数有selectpollepoll,今天主要使用poll函数。
poll()接受一个指向结构'struct po**d'列表的指针,其中包括了你想测试的文件描述符和事件。事件由一个在结构中事件域的比特掩码确定。当前的结构在调用后将被填写并在事件发生后返回。
函数原型:
#include<poll.h>int poll(struct po**d *fds, nfds_t nfds, int timeout);struct po**d{    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_PO**D_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 po**d po**d_arr[MAX_PO**D_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);      }  po**d_arr[0].events = POLLRDNORM;/*only read event*/po**d_arr[0].fd = server_socket_fd_conn1;po**d_arr[1].events = POLLRDNORM;/*only read event*/po**d_arr[1].fd = server_socket_fd_conn2;    while(1){poll_ret = poll( po**d_arr, MAX_PO**D_NUM,-1);if( po**d_arr[0].revents & POLLRDNORM ){/*connect 1 process task*/pthread_create( &thread_conn1, NULL, server_conn_handel.Server_Process_Client_Conn1, (void *)(&po**d_arr[0].fd));}if( po**d_arr[1].revents & POLLRDNORM ){/*connect 2 process task*/pthread_create( &thread_conn2, NULL, server_conn_handel.Server_Process_Client_Conn2, (void *)(&po**d_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 8000ip 127.0.0.1 port 8001
IPLC直译过来是国际私有租赁线路。IPLC产品相对于普通线路的最大优势在于不用担心IP不可用,节省下来更换IP的费用。另外,IPLC专线的成本比较高,相应的延迟时间比较短,速度也比较快。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

论坛客服/商务合作/投诉举报:2171544 (QQ)
落伍者创建于2001/03/14,本站内容均为会员发表,并不代表落伍立场!
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论!
落伍官方微信:2030286 邮箱:(djfsys@gmail.com|tech@im286.com)
© 2001-2014

浙公网安备 33060302000191号

浙ICP备11034705号 BBS专项电子公告通信管[2010]226号

  落伍法律顾问: ITlaw-庄毅雄

手机版|找回帐号|不能发帖?|Archiver|落伍者

GMT+8, 2024-4-25 02:33 , Processed in 0.101006 second(s), 31 queries , Gzip On.

返回顶部