获取用于 TCP 连接的随机端口

Get a random port for TCP connection

本文关键字:随机 连接 用于 TCP 获取      更新时间:2023-10-16

我有一个客户端和一个服务器应用程序。当客户端想要发送文件时,我使用的是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