3
我有一個問題,我創建兩個UDP套接字,將它們綁定到端口0的環回地址(請求堆棧分配一個臨時端口)。我的理解是,兩個套接字應該位於不同的端口上。在下面的代碼示例中,兩個套接字都報告在同一個IP地址和端口上。爲什麼綁定返回相同的臨時端口?
#include <stdio.h>
#include <arpa/inet.h>
int main(int, char**)
{
int fd1 = ::socket(AF_INET, SOCK_DGRAM, 0);
if (fd1 < 0)
{
perror("fd1 socket()");
return -1;
}
int fd2 = ::socket(AF_INET, SOCK_DGRAM, 0);
if (fd2 < 0)
{
perror("fd2 socket()");
return -1;
}
// Set SO_REUSEADDR for both sockets
int reuse = 1;
if (::setsockopt(fd1, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("fd1 SO_REUSEADDR failed");
return -1;
}
if (::setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("fd2 SO_REUSEADDR failed");
return -1;
}
sockaddr_storage storage;
socklen_t addrlen = sizeof(storage);
sockaddr_in& addr = reinterpret_cast<sockaddr_in&>(storage);
addr.sin_family = AF_INET;
addr.sin_port = 1234;
addr.sin_port = 0;
if (::inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) <= 0)
{
perror("Failed to create address 127.0.0.1");
return -1;
}
sockaddr* pAddr = reinterpret_cast<sockaddr*>(&storage);
if (::bind(fd1, pAddr, addrlen) < 0)
{
perror("bind fd1 failed");
return -1;
}
// Get the local address for fd1
addrlen = sizeof(storage);
if (::getsockname(fd1, pAddr, &addrlen))
{
perror("getsockname for fd1 failed");
return -1;
}
char straddr[INET_ADDRSTRLEN];
if (!inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr)))
{
perror("inet_ntop for fd1 failed");
return -1;
}
printf("fd1=%d addr=%s:%d\n", fd1, straddr, addr.sin_port);
if (::bind(fd2, pAddr, addrlen) < 0)
{
perror("bind fd2 failed");
return -1;
}
// Get the local address for fd2
addrlen = sizeof(storage);
if (::getsockname(fd2, pAddr, &addrlen))
{
perror("getsockname for fd2 failed");
return -1;
}
if (!inet_ntop(AF_INET, &addr.sin_addr, straddr, sizeof(straddr)))
{
perror("inet_ntop for fd2 failed");
return -1;
}
printf("fd2=%d addr=%s:%d\n", fd2, straddr, addr.sin_port);
return 0;
}
該代碼給出了下面的輸出...
fd1=4 addr=127.0.0.1:1933
fd2=5 addr=127.0.0.1:1933
我需要在同一(本地)IP地址都插座,但不同的端口。任何人都可以解釋爲什麼兩個套接字共享相同的端口?任何人都可以提出修正?
這不是SO_REUSEADDR選項。刪除它意味着第二個綁定失敗。您應該能夠將兩個UDP套接字綁定到相同的接口並具有不同的端口。 – Drew 2012-02-21 21:43:07
我還應該提到,如果我將fd2的綁定移動到fd1的綁定下方,我會得到不同的端口。很奇怪。我無法解釋這種行爲。 – Drew 2012-02-21 21:44:52
這是因爲綁定fd1後,您可以使用'paddr'調用'getsockname()'。所以你的第二個綁定請求分配給fd1的同一個端口號。設置'SO_REUSEADDR'會導致它允許,即使這不是你想要的。確保在第二次綁定之前重置「paddr」。 – 2012-02-21 22:36:13