listen() игнорирует значение backlog
Как я понимаю, отставание определяет размер очереди подключения. Любые дополнительные запросы, превышающие этот размер в этот момент, будут отбрасываться (верно это утверждение??).
Теперь у меня очень простая программа server.c
socket()
bind()
listen(..., 5)
while(1)
{
accept()
read()
write()
sleep(3)
close()
}
Теперь я запускаю 8 клиентов одновременно для подключения к этому серверу. Удивительно, но сервер обслуживает все 8 клиентов, но вместо этого он должен ставить в очередь только 5 клиентов, а запросы остальных 3 клиентов должны быть отклонены. Другим интересным моментом является то, что даже если я задаю это значение невыполненного задания как 0, результат остается тем же. Затем я попытался комментировать вызов listen(), при этом все 8 клиентских соединений отклоняются.
Может ли кто-нибудь предоставить какие-либо материалы по этому вопросу.
3 ответа
Аргумент backlog - это подсказка о размере очереди. Таким образом, вы не можете рассчитывать на то, что вы делаете то, что просите.
listen()
Этот ответ, кажется, покрывает это.
И еще информация, цитата из справочной страницы listen(2) в моей системе Ubuntu:
Аргумент backlog определяет максимальную длину, до которой может увеличиваться очередь ожидающих соединений для sockfd. Если запрос соединения приходит, когда очередь заполнена, клиент может получить ошибку с указанием ECONNREFUSED или, если базовый протокол поддерживает повторную передачу, запрос может быть проигнорирован, так что последующая повторная попытка соединения будет успешной.
Обратите внимание, что везде написано "может".
Server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
int main()
{
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_un server_address;
struct sockaddr_un client_address;
unlink(“server_socket”);
server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, “server_socket”);
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 5);
while(1)
{
char ch;
printf(“server waiting\n”);
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_address, &client_len);
read(client_sockfd, &ch, 1);
ch++;
write(client_sockfd, &ch, 1);
sleep(3);
close(client_sockfd);
}
}
Client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/un.h>
#include <unistd.h>
int main()
{
int sockfd;
int len;
struct sockaddr_un address;
int result;
char ch = ‘A’;
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
address.sun_family = AF_UNIX;
strcpy(address.sun_path, “server_socket”);
len = sizeof(address);
result = connect(sockfd, (struct sockaddr *)&address, len);
if(result == -1)
{
perror(“oops: client1”);
exit(1);
}
write(sockfd, &ch, 1);
read(sockfd, &ch, 1);
printf(“char from server = %c\n”, ch);
close(sockfd);
exit(0);
}
Я прослушал man в моей системе и получил следующее описание:
ОПИСАНИЕ
Функция listen() помечает сокет, называемый sockfd, как пассивный сокет, то есть как сокет, который будет использоваться для приема входящих запросов на соединение с помощью accept(2). Аргумент sockfd является дескриптором файла, который ссылается на сокет типа SOCK_STREAM или SOCK_SEQPACKET. Аргумент backlog определяет максимальную длину, до которой может увеличиваться очередь ожидающих соединений для sockfd. Если запрос соединения приходит, когда очередь заполнена, клиент может получить ошибку с указанием ECONNREFUSED или, если базовый протокол поддерживает повторную передачу, запрос может быть проигнорирован, так что последующая повторная попытка соединения будет успешной.