请教Linux下服务器用select处理一个socket对应的多个客户端

francisko 2012-04-13 04:08:24
小弟刚接触linux网络编程不久,现在用select做服务器端并行处理,收多个客户端的数据,但是调试过程中始终只能进通过FD_ISSET检测到2次数据到达,再多就收不到了,请教各位高人,下面是相关部分代码:


//socket
socket_listen_fd = Socket(AF_INET, SOCK_STREAM, 0);

bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = 0;

//listen a random port
Listen(socket_listen_fd, 20);//

//set for select read
maxfd = socket_listen_fd;
maxi = -1;
for(i = 0; i<FD_SETSIZE; i++)
{
client[i] = -1;
}
FD_ZERO(&allset);
FD_SET(socket_listen_fd, &allset);

while (1)
{
rset = allset;
nready = select(maxfd+1, &rset, NULL, NULL, NULL);

if(nready == -1)
{
perr_exit("select err");
}

//new client connection
if(FD_ISSET(socket_listen_fd, &rset))
{
connfd = Accept(socket_listen_fd, (struct sockaddr *)&client_addr, &client_addrlen);

//find an unused
for(i = 0; i < FD_SETSIZE; i++)
{
if(client[i] < 0)
{
client[i] = connfd;
break;
}
}

if(i == FD_SETSIZE)
{
perr_exit("too many clients");
}

//add new client's decriptor to set
FD_SET(connfd, &allset);

//max used file descriptor
if(connfd > maxfd)
maxfd = connfd;
//client index
if(i > maxi)
maxi = i;
//no more readable fd
if(--nready == 0)
continue;
}

//check all clients for data
for(client_index = 0; client_index <= maxi; client_index++)
{
if((sockfd = client[client_index]) == socket_listen_fd)
continue;
if(FD_ISSET(sockfd, &rset))
{
if((n = Read(sockfd, buf_in, MAXLINE)) == 0)
{
//connection closed by client
Close(sockfd);
FD_CLR(sockfd, &allset);
client[client_index] = -1;
}
else if(n == -1)
{
printf("Read err\n");
}
else
{
process_client();
}

//no more readable fd
if(--nready == 0)
break;
}
}
}
...全文
591 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
francisko 2012-04-14
  • 打赏
  • 举报
回复
代码太长了,贴不上啊 :(
sundayX 2012-04-14
  • 打赏
  • 举报
回复
上面的代码没有问题的,在每次循环时又都设置了rset = allset;
把服务端和客户端的所有代码列一下,我调一下试试。
francisko 2012-04-14
  • 打赏
  • 举报
回复
查资料后发现每次重新开始循环的时候应该用FD_ZERO清空可读可写属性的集合,我又加入了这部分代码,但是还是只能收到两次数据

while (1)
{
FD_ZERO(&rset);

FD_SET(socket_listen_fd, &rset);

for(i = 0; i <= maxi; i++)
{
if(client[i])
{
FD_SET(client[i], &rset);
}
}
许威威 2012-04-14
  • 打赏
  • 举报
回复
我们也刚好讲这方面的知识,难道楼主也是emsd1201班的?
CrazyBW 2012-04-13
  • 打赏
  • 举报
回复
代码应该没问题~~~~这个代码和 Unix网络编程 的一段代码及其相似~~~
francisko 2012-04-13
  • 打赏
  • 举报
回复
我重新检查了下,下面这部分我如果修改一下,加入调试信息

//new client connection
if(FD_ISSET(socket_listen_fd, &rset))
{
connfd = Accept(socket_listen_fd, (struct sockaddr *)&client_addr, &client_addrlen);
printf("client connected~~~~~~~~~~~~~~~~~~~~~~~\n");

加入调试信息:

//check all clients for data
for(client_index = 0; client_index <= maxi; client_index++)
{
printf("fd1 changing***************\n");
if((sockfd = client[client_index])<0)
//if((sockfd = client[client_index]) == socket_listen_fd)
continue;
if(FD_ISSET(sockfd, &rset))
{
printf("fd2 changing***************\n");

如果连4个客户端,结果显示:
client connected~~~~~~~~~~~~~~~~~~~~~~~
fd1 changing***************
fd2 changing***************
client connected~~~~~~~~~~~~~~~~~~~~~~~
client connected~~~~~~~~~~~~~~~~~~~~~~~
fd1 changing***************
fd1 changing***************
fd1 changing***************
fd2 changing***************
client connected~~~~~~~~~~~~~~~~~~~~~~~
上面结果说明4次accept都成功了,但是到fd2那里只进去2次,所以我还是觉得这段代码有问题
francisko 2012-04-13
  • 打赏
  • 举报
回复
一次开多个客户端,也只能收到2次数据,无论是从哪个客户端收到的
谢谢,我再检查下其他部分代码
sundayX 2012-04-13
  • 打赏
  • 举报
回复
这个代码应该没有问题。找找其他方面原因。
sundayX 2012-04-13
  • 打赏
  • 举报
回复
一个客户端连上时,服务端只能收到该客户端的2次数据?
francisko 2012-04-13
  • 打赏
  • 举报
回复
应该是if((sockfd = client[client_index])<0)
这段代码是我从《Linux C编程一站式学习》里面拿过来用的
但是这样也是只能收到2次数据
fishion 2012-04-13
  • 打赏
  • 举报
回复
client没有赋过socket_listen_fd这个值吧,那怎么会有if((sockfd = client[client_index]) == socket_listen_fd)这一段了

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧