我想知道TCP中bind()的确切功能。将本地地址“绑定”到套接字是什么意思?如果它正在为套接字分配端口号,那么为什么我们不在客户端中使用它?我知道端口是由操作系统在客户端自动分配的,但我并没有全面了解所有这些是如何工作的。
在bind()之后,我们听()。绑定是如何与listen()相关的? listen()是否知道bind()已被执行?如果是这样,bind()会做出哪些更改以便知道它?我的意思是,成功执行的返回零如何帮助?
我已经经历了很多定义,但是我无法详细了解所有这些。所以,如果有人能够向我解释这一点,我将不胜感激。
答案 0 :(得分:19)
它分配“本地”端的端口号。
对于服务器套接字,这是最终的方法 - 它正是所需要的:例如,将套接字绑定到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)
答案 1 :(得分:10)
bind()
定义连接的本地端口和接口地址。如果之前没有完成connect()
,则bind("0.0.0.0", 0)
执行隐式listen()
。<0被视为“任意”。
对于传出连接,这通常是可接受的并且是首选的。操作系统将简单地绑定到“所有接口”并选择一些高编号的未使用端口。如果服务器希望您来自特定端口或端口范围,则只需要在客户端上绑定。有些服务只允许端口号小于1024的连接,只能由超级用户绑定,但现在每个人都控制自己的机器并不是很有意义。
对于传入连接,您必须绑定到已知端口,以便客户端知道与您联系的位置。一旦他们这样做,他们就给服务器提供了本地地址/端口,以便通信可以双向流动。 bind()
仅在{{1}}来电后才能使用。
所有套接字都必须绑定,无论它们是UDP,TCP还是其他。它并不总是明确地完成。
答案 2 :(得分:8)
它将套接字“绑定”到一个地址,否则它不知道它应该监听哪个地址(ip-address / port对)。
bind
也可以在客户端使用。一个示例是在具有连接到同一网络的多个网卡的计算机上,但客户端只希望被视为来自一个特定的网络地址。
绑定不仅用于TCP套接字,也用于UDP套接字,以及其他协议。
答案 3 :(得分:0)
我知道这是一个老问题,但我有一个新答案:)
您可能希望连接到每个ip只允许有限数量的传入连接的服务器。
如果您有多个网络接口卡(因此可以连接多个可能的传出ips),您可以使用bind(),在每个ips上手动循环,以平衡您的连接,因此可以多次使用许多联系,否则将被允许。
要获取接口和ips的列表,请参阅this answer。