sockaddr.sin_port = 1337 не соответствует "реальному" открытому порту
Я пытаюсь сделать очень простой сервер, который принимает соединение.
int sock, serv;
struct sockaddr_in in_sock;
serv = socket(AF_INET, SOCK_STREAM, 0);
in_sock.sin_addr.s_addr = 0;
in_sock.sin_port = 1337;
in_sock.sin_family = AF_INET;
bind(serv, (struct sockaddr *)&in_sock, sizeof(in_sock));
listen(serv, 0);
client = accept(serv, 0, 0);
Однако при попытке подключиться к 127.0.0.1:1337 я получаю сообщение об отказе в подключении:
(НЕИЗВЕСТНО) [127.0.0.1] 1337 (?): Соединение отказано
Однако простой netstat -tcpan
показывает мне, что порт действительно открыт:
tcp 0 0 0.0.0.0:14597 0.0.0.0:* LISTEN
Если я установлю sin_port с гораздо более высокими портами, он, кажется, будет работать правильно
Что мне здесь не хватает? Почему не открыт порт 1337? Вроде бы тоже бесплатно.
2 ответа
Поле номера порта в struct sockaddr_in
хранится в сетевом порядке байтов. Это означает, что вы должны использовать htons()
при сохранении значения к нему:
in_sock.sin_port = htons(1337);
В противном случае номер порта будет заменен байтом. Что именно здесь произошло:
1337 = 0x0539
14597 = 0x3905
listen(serv, 0);
Второй аргумент listen
является backlog
и если мы посмотрим на документацию для прослушивания:
Аргумент backlog определяет максимальную длину, до которой может увеличиваться очередь ожидающих соединений для sockfd. Если запрос соединения приходит, когда очередь заполнена, клиент может получить ошибку с указанием ECONNREFUSED или, если базовый протокол поддерживает повторную передачу, запрос может быть проигнорирован, так что последующая повторная попытка соединения будет успешной.
ECONNREFUSED
это именно то сообщение об ошибке, которое вы получаете, потому что резерв заполнен (он может содержать 0 соединений, поэтому он всегда заполнен). Вы должны увеличить это число по крайней мере до 1, но большее количество может быть лучше listen(serv, 10);
,