У меня есть клиент и серверные приложения. Когда клиент хочет отправить файл, я использую TCP-соединение. когда я использую постоянный номер порта для используемого соединения (сервер получает файл).
Я хочу использовать случайный порт, поэтому я попытался установить порт на 0.
мой код:
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = 0;
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
cout << "failed to bind with errno: "<< errno << endl;
exit(1);
}
Связывание работает, но с портом 0 вместо случайного порта, как ожидалось.
Что я делаю не так?
Ну, проблема решена. Я добавил вызов getsocketname
if (getsockname(sockfd, (struct sockaddr *)&serv_addr, &len_inet) < 0){
cout << "failed to get hostname with errno: "<< errno << endl;
exit(1);
}
bind()
не обновляет структуру адресов, которые вы передаете ей. Это параметр const
. Если вы хотите знать, какой порт был выбран, когда вы указали нуль, вы должны использовать getsockname().
Когда у вас есть доступное повышение, это выглядит намного более очевидным и переносимым:
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
int getFreeTCPPort(std::string ipv4)
{
using namespace boost::asio;
io_service service;
ip::tcp::socket socket(service);
socket.open(ip::tcp::v4());
socket.bind(ip::tcp::endpoint(ip::address::from_string(ipv4), 0));
return socket.local_endpoint().port();
}
Конечно, это не ответ на ваш вопрос напрямую, но когда код не требует пояснений, возможно, вопрос просто не подходит.
Этот небольшой инструмент C поможет вам: https://github.com/yegor256/random-tcp-port
Просто скомпилируйте его с помощью make
а затем запустите ./reserve