谈linux socket poll的简单理解

本文介绍了Linux下使用socket进行通信的基本步骤,并重点讲解了poll机制。poll用于监听多个文件描述符的事件,如POLLIN表示有数据可读,POLLOUT表示可写,POLLERR表示错误事件等。通过示例代码展示了如何使用poll实现服务器监听和接受客户端连接,以及处理读写事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

v

对于linux socket通信,几个基本流程

sockfd=socket(AF_INET,SOCK_STREAM,0);

bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));

listen(sockfd,most_connect);

acceptfd=accept(sockfd,(struct sockaddr*)&client_addr,&len);

过后就是一个while循环,和客户端之间的read,write;

 

过后我们还可以通过poll来解决多个客户端和服务器的并发问题,我们可以通过man poll查看其函数用法。

       #include <poll.h>//poll函数包含在此库里。
       int poll(struct pollfd *fds, nfds_t nfds, int timeout);
       #define _GNU_SOURCE
       #include <poll.h>
       int ppoll(struct pollfd *fds, nfds_t nfds,
               const struct timespec *timeout, const sigset_t *sigmask);
DESCRIPTION
       poll() performs a similar task to select(2): it waits for one of a set of file descriptors to become ready to perform I/O.
       The  set  of  file descriptors to be monitored is specified in the fds argument, which is an array of nfds structures of the following
           struct pollfd {
               int   fd;         /* file descriptor文件描述符*/
               short events;     /* requested events等待的事件 */
               short revents;    /* returned events实际发生的事件 */
           };

              POLLIN There is data to read.d读事件

              POLLPRI
                     There is urgent data to read 高级的读事件

              POLLOUT
                     Writing now will not block.写事件

   

              POLLERR
                     Error condition (output only).错误事件

              POLLHUP
                     Hang up (output only).错误事件

              POLLNVAL
                     Invalid request: fd not open (output only).错误事件

代码实例:

#include <stdio.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <poll.h>
#include <unistd.h>
#include <sys/socket.h>
#define PROT 6666
#define SOMAXCON 10
#define OPEN_MAX 1024

int main()
{
 int P;
 int  maxi;
 int sockfd,bindnes,acceptfd;
 int on = 1;
 int i;
 char buf[1024];
 struct sockaddr_in server_addr,client_addr;
 struct pollfd client[OPEN_MAX];此处创建结构体数组client[];
 sockfd=socket(AF_INET,SOCK_STREAM,0);
 if(sockfd < 0)
 {
  printf("create socket fail%s\n",strerror(errno));
  exit(-1);
 }
 memset(&server_addr,0,sizeof(server_addr));
 server_addr.sin_family=AF_INET;
 server_addr.sin_port=htons(PROT);
 server_addr.sin_addr.s_addr=INADDR_ANY;
 setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
 bindnes = bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));
 if(bindnes < 0)
 {
  printf("bind fail%s\n",strerror(errno));
  exit(-1);
 }
 if(listen(sockfd,SOMAXCON)<0)
 {
  printf("listen fail%s\n",strerror(errno));
  exit(-1);
 }
 printf("waiting connection\n");
 client[0].fd=sockfd;//此client第一个描述符赋值为sockfd,事件为读事件。
 client[0].events=POLLIN;
 for(i=1;i<OPEN_MAX;i++)
 {
  client[i].fd = -1;此后先把除第一个以外所有的fd初始值为-1
 }
 maxi=0;描述符个数
 for(;;)
 {
  P=poll(client,maxi+1,-1);//poll函数
  if(P<0)
  {
   printf("poll fail%s\n",strerror(errno));
   break;
  }
  if(P==0)
  {
   printf("time out %s\n",strerror(errno));超时过后继续等待事件
   continue;
  }
  printf("poll ok!\n");

  if(client[0].revents & POLLIN)判断是发生client[0]的事件而且为读事件。
  {
   socklen_t len=sizeof(client_addr);
   acceptfd=accept(sockfd,(struct sockaddr*)&client_addr,&len);过后accept
   if(acceptfd < 0)
   {
    printf("accept fail%s\n",strerror(errno));
    break;
   }
   for(i=1;i<OPEN_MAX;i++)
   {
    if(client[i].fd < 0)
    {
     client[i].fd=acceptfd;将acceptfd该文件描述符添加到client[]这个文件描述符集中
     break;
    }
    if(OPEN_MAX==i)
    {
     printf("too many connection%s\n");
     exit(-1);
    }
    if(maxi<i)
    {
     maxi=i;
    }
    if(--P<=0)
     continue;
   }
   for(i=0;i<OPEN_MAX;i++)
   {
    if(client[i].fd < 0) continue;
    if(client[i].revents & POLLIN)//再次遍历文件描述符集,遍历到accpetfd文件描述符,切为读操作
    {
     while(1)
     {
      int n = read(acceptfd,buf,sizeof(buf));过后通过read函数读取客户端发送的数据
      if(n == 0)
      {
       close(client[i].fd);客户端关闭过后关闭该文件描述符,此后该fd重新置为-1
       client[i].fd=-1;
       continue;
      }
      if(n < 0)
      {
       printf("read fail%s\n",strerror(errno));
       exit(-1);
      }
      printf("read %d bytes, data %s\n\n",n,buf);
      write(acceptfd,buf,n);
     }
     
    }
   }
  }
 }
 return 0;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值