我尝试在Linux平台上使用C创建客户端/服务器系统。我想听四个不同的端口。因此,我创建了四个文件描述符,每个端口一个。此外,该进程将fd绑定到端口并开始监听它。这很好用。
此外,我使用select()
来监听连接,在那里我遇到了问题。在第一次运行中,程序在select时等待,直到连接客户端。我用telnet发送一个字符串到服务器后继续。但是在循环的第二次运行中,程序在select处再次停止,并且只要新客户端连接就等待。即使我通过telnet发送一个新字符串,它也会在建立新连接后等待并处理。我使用的示例类似于this link。
因此我不使用超时。
为什么它会在select时等待新连接?我该如何处理这个问题?
我的代码:
FD_ZERO(&read_sock);
FD_SET(fd[0], &read_sock);
FD_SET(fd[1], &read_sock);
FD_SET(fd[2], &read_sock);
FD_SET(fd[3], &read_sock);
while(TRUE){
fprintf(stderr,"Waiting for incoming connections...\n");
status = select(maxfd+1,&read_sock,NULL,NULL,NULL);
fprintf(stderr,"Number of fd: %d\n",status);
if(status>0){
for(int i=0; i< FD_SET_SIZE; i++){
if(FD_ISSET(fd[i], &read_sock)){
fd_accept=accept(fd[i],(struct sockaddr*)&client_address[i], &len);
if(client_sock[i] < 0) {
client_sock[i] = fd_accept;
}
int lenght = recv(client_sock[i],data,BUFFER-1,0);
if(lenght>0){
data[lenght] = '\0';
fprintf (stderr,"Received: %s\n", data);
}else if(lenght==0){
getpeername(fd[i],(struct sockaddr*)&client_address[i], &len);
close(fd[i]);
client_sock[i] = -1;
}else{
fprintf(stderr,"Error: %d\n",errno);
}
char string[] = "Test"; //sends a char Test to the client
write(client_sock[i],&string,sizeof(string));
}
}
}
}
答案 0 :(得分:3)
select
是阻止操作。从手册页:
select() and pselect() allow a program to monitor multiple file descriptors,
waiting until one or more of the file descriptors become "ready" for some class
of I/O operation (e.g., input possible). A file descriptor is considered ready
if it is possible to perform the corresponding I/O operation (e.g., read(2))
without blocking.
由于你给它的描述符是监听器套接字,它将阻塞,直到任何一个都有一个新的套接字。
如果你想在其中一个接受的套接字上监听数据,你需要在套接字描述符上select
,你存储在client_address
向量中。
您的代码有效地侦听新连接,接受它,读取数据,返回写入内容然后在不关闭它的情况下抛出套接字。