Unix C 程序---socket 和 select 函数

问题描述 投票:0回答:2

我刚刚开始学习 Unix C 编程,有一个问题我无法解决。在这个程序中,我制作了一个带有套接字和选择功能的简单服务器。当我使用不同的终端启动尝试连接服务器的客户端程序时,服务器可以接受新的客户端并成功连接(根据我的代码打印一句话)。但是,当我尝试在客户端程序中将客户端程序中的消息发送到服务器(通过 scanf() 和 send() )时,服务器只是阻塞在那里并且无法接收到消息。 您能帮我找出程序中的缺陷吗?非常感谢您的任何建议! 这是我的服务器程序的代码(我认为客户端程序没有问题):

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 #include <sys/types.h>
  5 #include <sys/socket.h>
  6 #include <netinet/in.h>
  7 #include <string.h>
  8 #include <fcntl.h>
  9 #include <sys/select.h>
 10 //all kinds of header 
 11 main(){
 12     int sfd;  //server's file descriptor 
 13     int fdall[100];  //array for client descriptor 
 14     int count=0;  //total number of clients
 15     int maxfd=0;   // max value of all descriptors
 16     char buf[1024]={0}; //used for receiving message from client, by recv()
 17     fd_set fds;  // readset in select()
 18     sfd=socket(AF_INET,SOCK_STREAM,0);
 19 
 20     struct sockaddr_in add;
 21     add.sin_family=AF_INET;
 22     add.sin_port=htons(9999);
 23     add.sin_addr.s_addr=inet_addr("192.168.122.1");
 24     int i,j,r;
 25 
 26     r=bind(sfd,(struct sockaddr*)&add,sizeof(add));
 27     if(r==-1) printf("bind:%m\n"),exit(-1);
 28     else puts("bind ok!");
 29     listen(sfd,10);
 30 
 31     while(1){
 32         FD_ZERO(&fds);
 33         maxfd=0;
 34         FD_SET(sfd,&fds);
 35         maxfd=maxfd>sfd?maxfd:sfd;
 36         for(i=0;i<100;i++){
 37             fdall[i]=-1;
 38         }
 39         r=select(maxfd+1,&fds,0,0,0);
 40         if(FD_ISSET(sfd,&fds)){
 41             fdall[count]=accept(sfd,0,0);
 42             puts("new client!");
 43             count++;
 44         }
 45         for(i=0;i<count;i++){
 46             if(FD_ISSET(fdall[i],&fds)!=-1&&fdall[i]!=-1){
 47                 r=recv(fdall[i],buf,1023,0);
 48                 for(j=0;j<count;j++){
 49                     if(fdall[j]!=-1){
 50                         send(fdall[j],buf,r,0);
 51                     }
 52                 }
 53             }
 54         }
 55     }
 56 }
c sockets unix posix-select
2个回答
1
投票

您不能使用

scanf
从套接字读取。
scanf
将从
STDIN
读取;这就是导致你受阻的原因。您也不能使用
fscanf
,因为这将需要
FILE *
,尽管可以使用
freopen
从套接字创建文件,但它会假设它可以坐在那里并且
read
尽其所能,而不是使用
select

您需要做的是

read
从套接字到缓冲区。当您拥有适当数量的数据(可能由换行符分隔)时,请使用
sscanf
(注意额外的
s
),确保您正在解析的字符串是
NUL
终止的。


0
投票

您当前的代码存在几个问题:

1.) 您的

fds
组中始终只有一组插座。这是您正在侦听新连接的套接字。您可能也想将所有连接到客户端的套接字放在那里。

2.) 测试

FD_ISSET(fdall[i],&fds)!=-1
没有任何意义。 FD_ISSET(fdall[i],&fds) 类似于一个布尔值,仅测试是否等于零。

3.) 您的测试

FD_ISSET(fdall[i],&fds)
始终结果为零,因为您已清除
sfd
中的所有值(
fds
除外)。请注意,
select
永远不会将文件描述符添加到集合中。它会删除那些会阻塞下一个 I/O 操作的内容。

4.) 在大循环的每次传递中,您将

fdall[i]
设置为
-1
,尽管之前的值可能是一个打开的套接字,并且您从未关闭该套接字。

在我看来,你需要重新考虑基本功能。您应该在大循环之前将

fdall[i]
设置为
-1
。在循环中,您应添加从
fdall[i]
fds
的所有套接字。当新客户端连接时,您应跳过下一个循环迭代,以避免使用此新套接字测试 FD_ISSET(这可能超出调用 select 的值
maxfd
)。希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.