談linux socket poll的簡單理解

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;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章