如何查找本地/端点端口号?

时间:2018-11-08 21:07:20

标签: c sockets udp winsock berkeley-sockets

我有一个使用Berkley套接字和Winsock(取决于平台)的UDP客户端程序。

基本上,它使用getaddrinfo(),然后使用socket(),然后使用sendto()sendto()获取getaddrinfo()返回的地址信息。我的代码如下:

struct addrinfo hint;
memset(&hint, 0, sizeof(hint));
hint.ai_socktype = SOCK_DGRAM;
struct addrinfo *address;
getaddrinfo("127.0.0.1", "9999", &hint, &address);

SOCKET s = socket(address->ai_family, address->ai_socktype, address->ai_protocol);
sendto(s, "test", 4, 0, address->ai_addr, address->ai_addrlen);

我的问题是,何时设置本地/临时端口号?是否设置了对sendto()的调用?如果我将更多数据发送到其他服务器,sendto()是否会重用相同的临时端口号?如何获得临时端口号(以独立于协议的方式)?我知道知道这可能没有用,并且NAT仍然可以更改它,但是我只是想了解所有这些如何更好地工作。

我也知道我可以使用bind()来设置本地端口,但是我的问题是当操作系统为我选择本地端口时会发生什么。

3 个答案:

答案 0 :(得分:0)

您需要getsockname函数:

struct sockaddr_storage ss;
socklen_t len;

len = sizeof(ss);
if (getsockname(s, (struct sockaddr *)&ss, &len) == 0) {
    // print contents of ss
}

它将使用套接字绑定到的地址和端口填充给定的sockaddr

此功能在winsock和Berkely套接字中均可用。

答案 1 :(得分:0)

sendto()的MSDN文档指出:

  

请注意:如果打开套接字,将进行setsockopt调用,然后进行sendto调用, Windows套接字将执行隐式bind函数调用

     

如果套接字未绑定,系统将为本地关联分配唯一值,然后将套接字标记为绑定。如果已连接套接字,则getsockname函数可用于确定与套接字关联的本地IP地址和端口。

     

如果未连接套接字,则可以使用getsockname函数来确定与套接字关联的本地端口号,但是返回的IP地址将设置为给定协议的通配符地址(例如,{对于IPv4为{1}}或“ 0.0.0.0”,对于IPv6为INADDR_ANY或“ ::”。

答案 2 :(得分:0)

可以 bind到端口 zero 0),这将导致操作系统找到一个开放的临时端口,您可以使用{ {1}},或者返回getsockname甚至在您尝试发送任何内容之前


关于何时由操作系统分配的临时端口来自ip(7) Linux manual page

  

[...]以下将临时端口分配给套接字   情况:

     
      
  • 套接字地址中的端口号在以下情况下指定为0    呼叫EADDRINUSE;

  •   在以前未绑定的流套接字上调用
  • bind(2)

  •   
  • listen(2)在以前未使用的套接字上被调用    绑定;

  •   在以前未绑定的数据报套接字上调用
  • connect(2)

  •