select -贾文龙

select(09嵌入式-贾文龙-注释

/* server.c */
#include
#include
#include
#include
#include "wrap.c"

#define MAXLINE 80
#define SERV_PORT 8000

int main(int argc, char **argv)
{
       
int i, maxi, maxfd, listenfd, connfd, sockfd;
       
int nready, client[FD_SETSIZE];
        ssize_t n
;
        fd_set rset
, allset;
       
char buf[MAXLINE];
       
char str[INET_ADDRSTRLEN];//宏定义INET_ADDRSTRLEN用于保存网络二进制地址转换为点分十进制地址
        socklen_t cliaddr_len
;
       
struct sockaddr_in      cliaddr, servaddr;

        listenfd
= Socket(AF_INET, SOCK_STREAM, 0);//打开一个网络通讯端口

        bzero
(&servaddr, sizeof(servaddr));//初始化 servaddr 将整个结构体清零
        servaddr
.sin_family      = AF_INET;//设置地址类型为AF_INET
        servaddr
.sin_addr.s_addr = htonl(INADDR_ANY);//网络地址为INADDR_ANY
        servaddr
.sin_port        = htons(SERV_PORT);//端口号
       
       
       
int opt = 1;
        setsockopt
(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));


       
Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
       
//将参数listenfd和servaddr绑定在一起,使listenfd这个用于网络通讯的文件描述符监听servaddr所描述的地址和端口号
       
       
Listen(listenfd, 20);

        maxfd
= listenfd;       /* 初始化maxfd作为select的第一个参数--最大的文件描述符加一*/
        maxi
= -1;                      /* index into client[] array */
       
for (i = 0; i < FD_SETSIZE; i++)
                client
[i] = -1; /*初始化client[]为 -1 : 指示可获得的输入项*/
        FD_ZERO
(&allset);               //清空集合
        FD_SET
(listenfd, &allset);      //将listenfd文件描述符加入集合之中

       
for ( ; ; )
       
{
                rset
= allset;  /* structure assignment */
                nready
= select(maxfd+1, &rset, NULL, NULL, NULL);//确定rset中套接字的状态
               
if (nready < 0)
                        perr_exit
("select error");

               
if (FD_ISSET(listenfd, &rset)) //判断 listenfd 是否在rset中
               
{ /* new client connection */
                        cliaddr_len
= sizeof(cliaddr);
                        connfd
= Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);

                        printf
("received from %s at PORT %d\n",
                               inet_ntop
(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
                               ntohs
(cliaddr.sin_port));

                       
for (i = 0; i < FD_SETSIZE; i++)
                               
if (client[i] < 0)
                               
{
                                        client
[i] = connfd; /* save descriptor */
                                       
break;
                               
}
                       
if (i == FD_SETSIZE)
                       
{
                                fputs
("too many clients\n", stderr);
                               
exit(1);
                       
}

                        FD_SET
(connfd, &allset);        /* add new descriptor to set */
                       
if (connfd > maxfd)
                                maxfd
= connfd; /* for select */
                       
if (i > maxi)
                                maxi
= i;       /* max index in client[] array */

                       
if (--nready == 0)
                               
continue;       /* no more readable descriptors */
               
}

               
for (i = 0; i <= maxi; i++)
               
{       /* check all clients for data */
                       
if ( (sockfd = client[i]) < 0)
                               
continue;
                       
if (FD_ISSET(sockfd, &rset))
                       
{
                               
if ( (n = Read(sockfd, buf, MAXLINE)) == 0)
                               
{
                                       
/* connection closed by client */
                                       
Close(sockfd);
                                        FD_CLR
(sockfd, &allset);
                                        client
[i] = -1;
                               
} else
                               
{
                                       
int j;
                                       
for (j = 0; j < n; j++)
                                                buf
[j] = toupper(buf[j]);
                                       
Write(sockfd, buf, n);
                               
}

                               
if (--nready == 0)
                                       
break;  /* no more readable descriptors */
                       
}
               
}
       
}
}


执行过程:
   
服务器先运行,定义变量并初始化一些变量,for循环,把allset的值赋值给rset,调用select()等待客户端连接,如果有客户端运行,select()返回,判断nready如果小于0就说明出错 退出,否则就判断lisentfd是否在rset里面,在就接受连接,用connfd 代替listenfd 与客户端通信。输出 客户端ip 和端口 ,然后保存 新建的描述符,在判断是否有太多的客户端  若太多 退出。 否则 connfd 保存进allset 然后在把最大的 文件描述符赋值给maxfd.如果此时  --nready 等于0  那么 就再次循环把allset 的值赋值给rset 此时 select()已经有了一个套接字对象处于满足条件的状态。判断 lisentfd是否在rset里面 此时 rsetallset赋值 只有connfd 不再执行if后面的语句。
   
执行for循环把上一面新建的描述符赋值给sockfd 并判断这个描述符是否小于0 ,如果小于0说明 client[i]里面没有新的文件描述符,就再次回到第一个for循环处执行。否则就判断 sockfd 在不在rset中,如果在,在判断能不能从客户端读取数据,如果能就执行else下面的语句 并把处理过得数据传回客户端,如果不能 说明客户端一关闭连接,就把新建的文件描述符关闭,并从allset中删除,把client[i]赋值为-1。接着判断--nready是否等于0 如果等于0 就退出本次循环,否则在次循环,判断另一个客户端(client[i])是否有输入有输入就处理并返回客户端,没有就关闭另一个客户端描述符。循环结束时,在执行上一个循环 ,重新接受新的客户端请求。一直循环。
                   
 

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(527) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
posted @ 2016-03-30 10:26  张同光  阅读(67)  评论(0编辑  收藏  举报