//使用select将多进程的程序改成但进程的程序
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/time.h>
#include<sys/unistd.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<strings.h>
#include<string.h>
#include<sys/select.h>
#define LISTENQ 1024//listen最大的监听个数
#define MAXLINE 4096
int main()
{
int listenfd, connfd, sockfd;//监听套接字, 已连接的套接字
int i, maxfd, maxi;
socklen_t clilen;
ssize_t n;
char buf[MAXLINE];
int nready, client[1024];
fd_set rset, allset;//描述符集
struct sockaddr_in server_sockaddr, client_sockaddr;//IPv4套接字地址结构
if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
{
fprintf(stderr, "Socket failed\n");
exit(EXIT_FAILURE);
}
bzero(&server_sockaddr, sizeof(server_sockaddr));//结构体清零
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(9877);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);//通配地址
if(bind(listenfd, (struct sockaddr*)&server_sockaddr, sizeof(server_sockaddr)) == -1)//绑定
{
fprintf(stderr, "Bind failed\n");
exit(EXIT_FAILURE);
}
if(listen(listenfd, LISTENQ) == -1)
{
fprintf(stderr, "Listen failed\n");
exit(EXIT_FAILURE);
}
maxfd = listenfd;//监听套接字描述符
maxi = -1; //index into client[] array
for(i=0; i<LISTENQ; i++)
client[i] = -1;//初始化client数组,client数组记住每个新的已连接描述符
FD_ZERO(&allset);
FD_SET(listenfd, &allset);//allset所有的描述符
while(1)
{
rset = allset;//structure assignment
nready = select(maxfd+1, &rset, NULL, NULL, NULL);//返回可读描述符的个数
if(FD_ISSET(listenfd, &rset))//如果有新的连接,连接这个客户端
{
clilen = sizeof(client_sockaddr);
connfd = accept(listenfd, (struct sockaddr*)&client_sockaddr, &clilen);
for(i=0; i<LISTENQ; i++)
{
if(client[i] < 0)
{
client[i] = connfd;//将新的已连接的套接字描述符加入client数组中
break;
}
}
if(i == LISTENQ)
exit(EXIT_FAILURE);
FD_SET(connfd, &allset);//add new dectiptor to set
if(connfd > maxfd)
maxfd = connfd;
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)
{
close(sockfd);
FD_CLR(sockfd, &rset);
client[i] = -1;
}
else
{
write(sockfd, buf, n);
memset(buf, 0, MAXLINE);
}
if(--nready <= 0)
break;//no more readable descriptors
}
}
}
}
select实现并发服务器
最新推荐文章于 2023-12-31 20:24:11 发布