我尝试了以下内容:
int sockfd = socket(...);
listen(sockfd, 10);
accept(sockfd, ...);
没有一个调用失败,程序刚刚开始阻塞,就像我调用了bind()一样。在这种情况下会发生什么?是否只是不可能接收连接,因为它没有本地地址或端口?或者它是否隐式分配了本地地址和端口,现在它正在监听那些?如果是这样,我该如何检索它们是什么?
答案 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派生库,这种行为可能是相同的。