57

我想知道 TCP 中 bind() 的确切功能。将本地地址“绑定”到套接字是什么意思?如果它为套接字分配一个端口号,那么我们为什么不在客户端使用它呢?我知道该端口是由操作系统在客户端自动分配的,但我没有全面了解这一切是如何工作的。

在bind()之后,我们listen()。绑定与listen() 有什么关系?listen() 会知道 bind() 已经执行了吗?如果是这样,bind() 会进行哪些更改以使其为人所知?我的意思是,成功执行返回零有什么帮助?

我已经经历了许多定义,但我无法详细了解所有这些。因此,如果有人可以向我解释这一点,我将不胜感激。

4

4 回答 4

31

它分配“本地”端的端口号。

对于服务器套接字,这是最终的方法——这正是所需要的:例如,将您的套接字绑定到 Web 服务器的端口 80。

然而,对于客户端套接字,本地地址和端口通常并不重要。所以你不bind()。如果服务器将其客户端限制为可能具有某个端口号或超出给定范围的端口号,您也可以bind()在客户端使用。

另一方面,您也可以listen()在尚未调用的套接字上进行操作bind()(实际上我不确定,但这是有道理的)。在这种情况下,您的服务器端口将是随机的,并且服务器进程将通过不同的方式将其端口传递给客户端。想象一个“双连接”协议,例如 FTP,其中有一个控制连接和一个数据连接。数据连接侦听的端口是完全任意的,但必须与另一端通信。所以使用“自动确定的端口”进行通信。

Python 中的一个示例:

import socket
s = socket.socket() # create your socket
s.listen(10) # call listen without bind
s.getsockname() Which random port number did we get?
# here results in ('0.0.0.0', 61372)

s2 = socket.socket() # create client socket
s2.connect(('localhost', 61372)) # connect to the one above
s3, x = s.accept() # Python specific use; s3 is our connected socket on the server side
s2.getpeername()
# gives ('127.0.0.1', 61372)
s2.getsockname()
# gives ('127.0.0.1', 54663)
s3.getsockname()
# gives ('127.0.0.1', 61372), the same as s2.getpeername(), for symmetry
s3.getpeername()
#gives ('127.0.0.1', 54663), the same as s2.getsockname(), for symmetry
#test the connection
s2.send('hello')
print s3.recv(10)
于 2012-10-06T19:55:14.843 回答
17

bind()定义连接的本地端口和接口地址。 如果之前没有做过connect()一个隐含的(零被视为“任何”)。bind("0.0.0.0", 0)

对于传出连接,这通常是可以接受和首选的。操作系统将简单地绑定到“所有接口”并选择一些高编号的未使用端口。如果服务器期望您来自特定端口或端口范围,您只需要在客户端上绑定。有些服务只允许来自小于 1024 的端口号的连接,这些只能由超级用户绑定,尽管现在每个人都控制自己的机器,这并不意味着什么。

对于传入连接,您必须绑定到已知端口,以便客户端知道在哪里与您联系。一旦他们这样做了,他们就为服务器提供了他们的本地地址/端口,以便通信可以双向流动。 listen()只会在bind()通话后工作。

所有套接字都必须绑定,无论它们是 UDP、TCP 还是其他。它并不总是明确地完成。

于 2012-10-07T13:54:55.680 回答
11

它将一个套接字“绑定”到一个地址,否则它不知道它应该监听哪个地址(IP 地址/端口对)。

bind可以在客户端使用。一个示例是在具有多个网卡连接到同一网络的计算机上,但客户端只想被视为来自一个特定的网络地址。

绑定不仅用于 TCP 套接字,还用于 UDP 套接字以及其他协议。

于 2012-10-06T19:55:04.323 回答
0

我知道这是一个老问题,但我有一个新答案:)

您可能希望连接到每个 IP 只允许有限数量的传入连接的服务器。

如果您有多个网络接口卡(因此有多个可能的传出 ip 进行连接),您可以使用 bind(),手动循环遍历每个 ip,以平衡您的连接,因此连接数是否则将被允许。

要获取您的接口和 ips 的列表,请参阅答案。

于 2017-08-02T01:05:11.443 回答