- #include "unp.h"
- 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];
- socklen_t clilen;
- struct sockaddr_in cliaddr, servaddr;
- listenfd = Socket(AF_INET, SOCK_STREAM, 0);
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(SERV_PORT);
- Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
- Listen(listenfd, LISTENQ);
- maxfd = listenfd; /* initialize */
- maxi = -1; /* index into client[] array */
- for (i = 0; i < FD_SETSIZE; i++)
- client[i] = -1; /* -1 indicates available entry */
- FD_ZERO(&allset);
- FD_SET(listenfd, &allset);
- /* end fig01 */
- /* include fig02 */
- for ( ; ; ) {
- rset = allset; /* structure assignment */
- nready = Select(maxfd+1, &rset, NULL, NULL, NULL);
- if (FD_ISSET(listenfd, &rset)) { /* 是否有新的连接进来*/
- clilen = sizeof(cliaddr);
- connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
- #ifdef NOTDEF
- printf("new client: %s, port %d\n",
- Inet_ntop(AF_INET, &cliaddr.sin_addr, 4, NULL),
- ntohs(cliaddr.sin_port));
- #endif
- for (i = 0; i < FD_SETSIZE; i++)
- if (client[i] < 0) {
- client[i] = connfd; /* 保存描述符到client数组中*/
- break;
- }
- if (i == FD_SETSIZE)
- err_quit("too many clients");
- FD_SET(connfd, &allset); /* add new descriptor to set */
- if (connfd > maxfd)
- maxfd = connfd; /* 设置maxfd值*/
- 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) {
- /*4connection closed by client */
- Close(sockfd);
- FD_CLR(sockfd, &allset); //从allset描述符集中清除该sockfd
- client[i] = -1;
- } else
- Writen(sockfd, buf, n);
- if (--nready <= 0)
- break; /* no more readable descriptors */
- }
- }
- }
- }
说明:该程序为多进程服务器模型的改进,采用select实现监听socket,当描述符集有i/o事件发生时,select就会返回一个活跃的reset集,接下来,通过采用FD_ISSET函数来判断,client数组中的socket是否在活跃的reset集中,从而做相应的处理。
这里存在一个问题,假定一个客户连接到该服务器上,发送一个字节的数据,然后进入到睡眠中,此时服务器端会阻塞在read调用中,以等待来自客户的下一个调用。
可行的办法设置为非阻塞式IO。下一节再采用。
阅读(1356) | 评论(0) | 转发(0) |