Сейчас я пытаюсь указать параметры с setsockopt()
используя следующий код:
// bind socket
// Use setsockopt() function to make sure the port is not in use
int yes = 1;
setsockopt(TCPSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
setsockopt(TCPSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
status = bind(TCPSocket, host_info_list->ai_addr, host_info_list->ai_addrlen);
if (status == -1) std::cout << "bind error" << std::endl ;
// listen for connections
status = listen(TCPSocket, 5);
if (status == -1) std::cout << "listen error" << std::endl ;
int new_sd;
struct sockaddr_storage their_addr;
socklen_t addr_size = sizeof(their_addr);
new_sd = accept(TCPSocket, (struct sockaddr *)&their_addr, &addr_size);
if (new_sd == -1) std::cout << "listen error" << std::endl ;
Заметка tv
это уже указанное время.
Когда я делаю только первый setsockopt()
звоните, все отлично работает. Однако с добавлением второй (которая не возвращает никаких ошибок) я сталкиваюсь со второй «ошибкой прослушивания», указанной в коде. Я не уверен, почему установка значения тайм-аута влияет на это, кто-то может объяснить?
Я не беру кредит на указанный код; он модифицирован из кода, представленного в руководстве здесь: http://codebase.eu/tutorial/linux-socket-programming-c/
Если вы видите диаграмму состояния TCP как этот Вы видите, что есть состояние под названием TIME_WAIT
при активном закрытии сокета. Это состояние может занять некоторое время, прежде чем оно закончится, до четырех минут в зависимости от RFC793.
Пока розетка находится в TIME_WAIT
Вы не можете привязать к интерфейсу, используя ту же пару адрес-порт, что и сокет, который находится в состоянии ожидания. Настройка SO_REUSEADDR
флаг om socket позволяет другим сокетам связываться с адресом, когда текущий сокет (с установленным флагом) находится в TIME_WAIT
государство.
SO_REUSEADDR
Опция наиболее полезна для серверных (пассивных, прослушивающих) сокетов.
Что касается вашей проблемы, после каждого звонка setsockopt
проверьте, что он возвращает, и если это -1
тогда вы проверяете errno
чтобы увидеть, что пошло не так. Ты можешь использовать perror
или же strerror
распечатать или получить печатаемую строку для ошибки, например
if (setsockopt(TCPSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0)
{
std::cerr << "Error setting the SO_REUSEADDR: " << strerror(errno) << '\n';
// Do something appropriate
}
Решение Йоахима отлично ответило на мой начальный вопрос и объяснило setsockopt (). Чтобы ответить на мой собственный вопрос после того, как выяснилось, что проблема была еще ниже в коде, тайм-аут влияет на способность сервера прослушивать порт. Скажем, время ожидания составляет всего 10 мс, сервер должен быть запущен, затем клиент, и за это время должно быть установлено соединение. Это не происходило в моем случае, поэтому возникла ошибка.