listen()而不调用bind()

时间:2009-04-12 00:35:51

标签: language-agnostic networking network-programming tcp

我尝试了以下内容:

int sockfd = socket(...);
listen(sockfd, 10);
accept(sockfd, ...);

没有一个调用失败,程序刚刚开始阻塞,就像我调用了bind()一样。在这种情况下会发生什么?是否只是不可能接收连接,因为它没有本地地址或端口?或者它是否隐式分配了本地地址和端口,现在它正在监听那些?如果是这样,我该如何检索它们是什么?

3 个答案:

答案 0 :(得分:11)

调用正在运行,但由于您没有显式绑定套接字,因此操作系统或系统库会为您隐式分配端口和默认绑定(与您在不调用{connect(2)时调用的情况完全相同{1}}首先)。另外,既然您之前询问过TCP的问题,我假设您在这里谈论的是Internet套接字。

找出操作系统绑定套接字的操作系统的名称因操作系统而异,因此您必须查找特定的操作系统,但大多数操作系统都提供bind(2)或类似的工具,您可以使用它来查询应用程序正在侦听哪些端口。

正如John在评论中提到的那样,您可以使用netstat来查找绑定套接字的名称。这是一个简短的例子:

getsockname(2)

// ... // Create socket and set it to listen (we ignore error handling for brevity) int sock = socket(AF_INET, SOCK_STREAM, 0); listen(sock, 10); // Sometime later we want to know what port and IP our socket is listening on socklen_t addr_size = sizeof(struct sockaddr_in); struck sockaddr_in addr; getsockname(sock, (struct sockaddr *)&addr, &addr_size); 现在将包含套接字正在侦听的IP地址和端口。

答案 1 :(得分:3)

正如其他人提到的,如果你没有绑定(),操作系统将分配一个端口。您可以在listen()之后使用getsockname()调用来查看分配了哪个地址/端口。然后,如果您将该地址/端口传送给客户端,则可以连接。

因此这是有道理的。你可以写一个程序,这是一个有趣的事情。

答案 2 :(得分:0)

我怀疑你永远不会得到联系。您可以在运行程序之前和之后通过在操作系统上执行相当于“netstat -an”的操作来检查是否有新的套接字监听。

我在C#中尝试了同样的事情:

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Listen(1);
socket.Accept();

我在第二行得到一个例外,它以迂回的方式通知我需要绑定。它当然适用于:

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(new IPEndPoint(IPAddress.Loopback, 4567));
socket.Listen(1);
socket.Accept();

我使用Udp套接字进行了测试,同样的事情,除非已经完成绑定,否则Windows对Listen调用不满意。由于.Net套接字调用只是围绕Winsock的包装器,因此对于Windows上的所有Winsock派生库,这种行为可能是相同的。