注:没有写socket流程
1.定义select相关变量
int listenfd,connfd,i;/*套接字描述符/链接描述符(录入环节)/变量*/ int nread,maxfd,maxi,sockfd;/*就绪数/最大链接描述符/用于记录链接描述符数组当前最大使用的下标,减少无用的遍历/链接描述符(区别在于此处用于I/O复用的遍历环节)*/int client[FD_SETSIZE];/*存放录入的链接描述符*/fd_set allest,rset;/*文件集合描述符:所有集合/就绪可读集合*/
2.select相关变量的相关数据初始化
maxfd = listenfd; /*初始化最大链接描述符,*/maxi = -1;for (i = 0; i < FD_SETSIZE; i++) client[i] = -1;FD_ZERO(&allest);/*清空allset描述符集*/FD_SET(listenfd, &allest);/*将监听描述符加到allset中*/
3.select 监视可读事件
rset = allest;nread = select(maxfd+1, &rset, NULL, NULL, NULL);/*调用select 监视可读事件*/
4.新的链接描述符放入数组和描述符集
if (FD_ISSET(listenfd, &rset))/*判断服务器端套接字中是否有变化(是否有新的链接)*/{cliaddr_lin = sizeof(cliaddr);connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_lin);for (i = 0; i < FD_SETSIZE; i++){if (client[i] < 0){client[i] = connfd;
/ /*新的链接描述符放入数组*/break;}}FD_SET(connfd, &allest);/* 将来自客户的连接connfd加入描述符集 */if (connfd > maxfd) maxfd = connfd;/*新的链接描述符*/if (i > maxi) maxi = i;if (--nread == 0) continue;}
5.批处理可读链接描述符
for (i = 0; i <= maxi; i++)
{if ((sockfd = client[i]) < 0) continue;if (FD_ISSET(sockfd, &rset)){if ((n = read (sockfd, buf, MAXLIN)) == 0){close(sockfd);FD_CLR(sockfd, &allest);client[i] = -1;}else{if (n < 0) perror("read:");if (n > 0) write(sockfd, buf, n);}if (--nread == 0) break;}
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>#define LINK_NUMBER 20
#define SERV_PORT 8000
#define MAXLIN 100int main(int argc, char const *argv[])
{int listenfd,connfd,i;int nread,maxfd,maxi,sockfd;int client[FD_SETSIZE];ssize_t n;fd_set allest,rset;socklen_t cliaddr_lin;struct sockaddr_in servaddr,cliaddr;char buf[MAXLIN],str[INET_ADDRSTRLEN];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, (struct sockaddr *)&servaddr, sizeof(servaddr));listen(listenfd,LINK_NUMBER);maxfd = listenfd;maxi = -1;for (i = 0; i < FD_SETSIZE; i++) client[i] = -1;FD_ZERO(&allest);FD_SET(listenfd, &allest);while(1){rset = allest;nread = select(maxfd+1, &rset, NULL, NULL, NULL);if (nread < 0){perror("select error:");break;}if (FD_ISSET(listenfd, &rset)){cliaddr_lin = sizeof(cliaddr);connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_lin);printf("received from %s at PORT %dn",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;break;}}if (i == FD_SETSIZE){perror("too many clients");exit(1);}FD_SET(connfd, &allest);if (connfd > maxfd) maxfd = connfd;if (i > maxi) maxi = i;if (--nread == 0) continue; }for (i = 0; i <= maxi; i++){if ((sockfd = client[i]) < 0) continue;if (FD_ISSET(sockfd, &rset)){if ((n = read (sockfd, buf, MAXLIN)) == 0){close(sockfd);FD_CLR(sockfd, &allest);client[i] = -1;}else{if (n < 0){perror("read:");}if (n > 0){write(sockfd, buf, n);}}if (--nread == 0) break;}}/*socket*//*while(1){if((n = read(connfd,buf,MAXLIN)) <= 0) {printf("err" );break;}printf("received from %s at PORT %d::%sn",inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),ntohs(cliaddr.sin_port),buf);write(connfd,buf,n);}close(connfd);*/}return 0;
}
Linux聊天室项目 – ChatRome(select实现)
Linux I/O复用之select函数详解
unix网络编程第二版
本文发布于:2024-02-02 09:49:49,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170683859042998.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |