Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2112703
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2015-06-17 16:51:04

1. 描述
1.1 流程描述
    a. 刚开始时select只轮询listenfd
    b. 当有client连接时,把accept之后的client的sockfd,加入到select中
    c. 这样select既轮询listenfd又轮询client的sockfd
    d. 当client有连接时,重复b
    e. 当client有数据时,读数据并返回
2. 源码
2.1 tcpserv.c
  1. cong@msi:/work/test/tcpip/12select/serv$ cat tcpserv.c
  2. #include "utils.h"

  3. int main ( int argc, char *argv[] )
  4. {
  5.     ssize_t n;
  6.     int i, maxi, maxfd;
  7.     int listenfd, connfd, sockfd;
  8.     int nready, client[FD_SETSIZE];
  9.     struct sockaddr_in servaddr, cliaddr;
  10.     fd_set rset, allset;
  11.     char buf[MAXLINE];
  12.     socklen_t clilen;
  13.     listenfd = socket(AF_INET, SOCK_STREAM, 0);                        --> 1. socket
  14.     if(listenfd< 0)
  15.         return -1;
  16.     bzero(&servaddr, sizeof(servaddr));
  17.     servaddr.sin_family = AF_INET;
  18.     servaddr.sin_port = htons(13999);
  19.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  20.     //inet_pton(AF_INET, TIME_SERV_ADDR, &servaddr.sin_addr);
  21.      
  22.     bind(listenfd, (const struct sockaddr*)&servaddr, sizeof(servaddr));  --> 2. bind
  23.     listen(listenfd, LISTENQ);                                            --> 3. listen
  24.     maxfd = listenfd;
  25.     maxi = -1;
  26.     for(i=0; i<FD_SETSIZE; i++)
  27.         client[i] = -1;
  28.     FD_ZERO(&allset);
  29.     FD_SET(listenfd, &allset);
  30.     while(1)
  31.     {
  32.         rset = allset;
  33.         nready = select(maxfd+1, &rset, NULL, NULL, NULL);     //刚开始时只监测listenfd,当有client连入时
  34.         if(nready<0)                                           //既监测listenfd又监测client
  35.             continue;
  36.         if(FD_ISSET(listenfd, &rset)) //new client connection
  37.         {
  38.             clilen = sizeof(cliaddr);
  39.             connfd = accept(listenfd, (struct sockaddr*)&cliaddr,&clilen);
  40.             for(i=0; i<FD_SETSIZE; i++)
  41.             {
  42.                 if(client[i] < 0)
  43.                 {
  44.                     client[i]=connfd;
  45.                     break;
  46.                 }
  47.             }
  48.             if(i==FD_SETSIZE)
  49.                 dbmsg("too many clients");
  50.             FD_SET(connfd, &allset);
  51.             if(connfd > maxfd)
  52.                 maxfd = connfd;
  53.             if(i>maxi) 
  54.                 maxi = i;      //maxi记录连接了的client个数
  55.             if(--nready <= 0)  //nready-->select监测到有变化的描述符个数
  56.                 continue;
  57.         }
  58.         for(i=0; i<=maxi; i++)
  59.         {
  60.             if( (sockfd = client[i]) < 0)
  61.                 continue;
  62.             if(FD_ISSET(sockfd, &rset))
  63.             {
  64.                 if( (n=read(sockfd, buf, MAXLINE)) == 0)    //当收到的数据个数为0时,说明client己关闭连接
  65.                 {
  66.                     close(sockfd);
  67.                     FD_CLR(sockfd, &allset);     //select不再轮询这个socket
  68.                     client[i] = -1;             //把client列表中这项置-1
  69.                 }else
  70.                     write(sockfd, buf, n);      //当收到的数据个数不为0时,就把数据写到client端
  71.                 if(--nready <= 0)  //nready-->select监测到有变化的描述符个数
  72.                     break;
  73.             }
  74.         }
  75.     }
  76.     return EXIT_SUCCESS;
  77. }
nready-->select临测到有变化的描述符个数,既包括listen的描述符,又包括accept之后client的socket描述符,
          -->当listen的描述符有变化时: 加入到select轮询队列,--nready
          -->当client的socket描述符有变化时: for循环处理每一个描述符,--nready,当为0时说明所有变化的socket都处理完成,则break
2.2 utils.h
  1. cong@msi:/work/test/tcpip/12select/serv$ cat utils.h
  2. #ifndef UTILS_H__
  3. #define UTILS_H__
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <sys/types.h> /* See NOTES */
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <time.h>
  11. #include <string.h>
  12. #include <errno.h>
  13. #include <signal.h>

  14. #define MAXLINE 1024

  15. #define LISTENQ 10
  16. #define dbmsg(fmt, args ...) printf("%s:%s[%d]: "fmt"\n", __FILE__,__FUNCTION__, __LINE__,##args)
  17. #define max(a,b) ((a) > (b) ? (a) : (b))

  18. #endif

serv.rar (下载后改名为serv.tar.gz)
client.rar (下载后改名为client.tar.gz)
阅读(1026) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~