Chinaunix首页 | 论坛 | 博客
  • 博客访问: 126156
  • 博文数量: 36
  • 博客积分: 94
  • 博客等级: 民兵
  • 技术积分: 200
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-23 17:34
文章分类
文章存档

2015年(1)

2013年(7)

2012年(3)

2011年(25)

分类:

2012-04-18 15:08:00


点击(此处)折叠或打开

  1. #include "unp.h"

  2. int main(int argc, char **argv)
  3. {
  4.     int i, maxi, maxfd, listenfd, connfd, sockfd;
  5.     int nready, client[FD_SETSIZE];
  6.     ssize_t n;
  7.     fd_set rset, allset;
  8.     char buf[MAXLINE];
  9.     socklen_t clilen;
  10.     struct sockaddr_in cliaddr, servaddr;

  11.     listenfd = Socket(AF_INET, SOCK_STREAM, 0);

  12.     bzero(&servaddr, sizeof(servaddr));
  13.     servaddr.sin_family = AF_INET;
  14.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  15.     servaddr.sin_port = htons(SERV_PORT);

  16.     Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

  17.     Listen(listenfd, LISTENQ);

  18.     maxfd = listenfd; /* initialize */
  19.     maxi = -1; /* index into client[] array */
  20.     for (i = 0; i < FD_SETSIZE; i++)
  21.         client[i] = -1; /* -1 indicates available entry */
  22.     FD_ZERO(&allset);
  23.     FD_SET(listenfd, &allset);
  24. /* end fig01 */

  25. /* include fig02 */
  26.     for ( ; ; ) {
  27.         rset = allset; /* structure assignment */
  28.         nready = Select(maxfd+1, &rset, NULL, NULL, NULL);

  29.         if (FD_ISSET(listenfd, &rset)) { /* 是否有新的连接进来*/
  30.             clilen = sizeof(cliaddr);
  31.             connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
  32. #ifdef NOTDEF
  33.             printf("new client: %s, port %d\n",
  34.                     Inet_ntop(AF_INET, &cliaddr.sin_addr, 4, NULL),
  35.                     ntohs(cliaddr.sin_port));
  36. #endif

  37.             for (i = 0; i < FD_SETSIZE; i++)
  38.                 if (client[i] < 0) {
  39.                     client[i] = connfd; /* 保存描述符到client数组中*/
  40.                     break;
  41.                 }
  42.             if (i == FD_SETSIZE)
  43.                 err_quit("too many clients");

  44.             FD_SET(connfd, &allset); /* add new descriptor to set */
  45.             if (connfd > maxfd)
  46.                 maxfd = connfd; /* 设置maxfd值*/
  47.             if (i > maxi)
  48.                 maxi = i; /* max index in client[] array */

  49.             if (--nready <= 0)
  50.                 continue; /* no more readable descriptors */
  51.         }

  52.         for (i = 0; i <= maxi; i++) { /* check all clients for data */
  53.             if ( (sockfd = client[i]) < 0)
  54.                 continue;
  55.             if (FD_ISSET(sockfd, &rset)) {
  56.                 if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
  57.                         /*4connection closed by client */
  58.                     Close(sockfd);
  59.                     FD_CLR(sockfd, &allset); //从allset描述符集中清除该sockfd
  60.                     client[i] = -1;
  61.                 } else
  62.                     Writen(sockfd, buf, n);

  63.                 if (--nready <= 0)
  64.                     break; /* no more readable descriptors */
  65.             }
  66.         }
  67.     }
  68. }



说明:该程序为多进程服务器模型的改进,采用select实现监听socket,当描述符集有i/o事件发生时,select就会返回一个活跃的reset集,接下来,通过采用FD_ISSET函数来判断,client数组中的socket是否在活跃的reset集中,从而做相应的处理。

这里存在一个问题,假定一个客户连接到该服务器上,发送一个字节的数据,然后进入到睡眠中,此时服务器端会阻塞在read调用中,以等待来自客户的下一个调用。
可行的办法设置为非阻塞式IO。下一节再采用。
阅读(1136) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~