我制作了一个小型客户端/服务器程序,其中服务器可以使用
select()
函数同时处理多个客户端。当我运行我的程序时,一切正常,直到我杀死客户端程序,当我杀死客户端程序时,服务器不会在 select()
处阻塞,但它只是在 while 循环中迭代。
当我将
FD_SETSIZE
中的 select(FD_SETSIZE, ©Fds, NULL, NULL, NULL);
更改为 master_socket + 1
时,它不会阻塞,因此工作正常。
GNU 库说: select 函数仅检查第一个 nfds 文件描述符。通常的做法是传递 FD_SETSIZE 作为该参数的值。 https://www.gnu.org/software/libc/manual/html_node/Waiting-for-I_002fO.html
为什么我会遇到这个错误?如何传入
FD_SETSIZE
并且仍然让程序阻塞在select()
?
服务器:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
int main()
{
system("clear");
printf("***SERVER STARTED***\n");
char message[125] = "Welcome to my server";
int master_socket = socket(AF_INET, SOCK_STREAM, 0);
fd_set masterFds, copyFds;
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8888);
socklen_t addrlen = sizeof address;
bind(master_socket, (struct sockaddr *)&address, sizeof(address));
listen(master_socket, 1);
FD_ZERO(&masterFds);
FD_SET(master_socket, &masterFds);
while (1)
{
copyFds = masterFds;
printf("Monitoring for connections...\n");
select(FD_SETSIZE, ©Fds, NULL, NULL, NULL); // When a socket wants to connect it's file descriptor gets stored in copyFds
for (int i = 0; i < FD_SETSIZE; i++)
{
if (FD_ISSET(i, ©Fds))
{
if (i == master_socket) // New connection
{
int accepted_socket = accept(master_socket, (struct sockaddr *)&address, &addrlen);
FD_SET(accepted_socket, &masterFds);
printf("[+] New connection accepted\n");
write(accepted_socket, message, sizeof(message)); // Send message to client
}
else
{
// Not finished yet
}
}
}
printf("End of while loop\n");
}
}
客户端(相同的标头):
int main()
{
system("clear");
int clientSocket = socket(AF_INET, SOCK_STREAM, 0), x;
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(8888);
serverAddress.sin_addr.s_addr = INADDR_ANY;
connect(clientSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
char serverResponse[125];
read(clientSocket, serverResponse, sizeof(serverResponse));
printf("test: %s\n", serverResponse);
scanf("%d", &x);
close(clientSocket);
}
如果客户端关闭其连接,您需要从
select
正在监视的描述符集中删除该 fd。否则,它会立即返回,期待您对此采取一些行动fd
。换句话说,添加如下内容:
char buf[1024];
ssize_t nr = read(i, buf, sizeof buf);
switch( nr ){
case -1:
perror("read");
/* fallthru */
case 0:
if( close(i) ){
perror("close");
}
puts("Client connection closed");
FD_CLR(i, masterFds);
break;
default:
fwrite(buf, 1, nr, stdout);
fflush(stdout);
}
在
else
子句中。 (“尚未完成”部分。)