该绑定到哪个端口

这对于每一个编写服务器的程序员而言都是一个非常重要的考量。应该选择随机端口吗?该如何知道是否已经有其他的程序将某个端口宣为己有?

任何在 0~65535 之间的端口都可以使用,但是在选用之前别忘了一些重要的约定。

规则1: 不要使用 0~1024 之间的端口。

这些端口是作为熟知 (well-known)端口并保留给系统使用的。例如HTTP默认使用端口80, SMTP默认使用端口25,rsync默认使用端口873。绑定到这些端口通常需要root权限。

规则2: 不要使用 49000~65535 之间的端口。

这些都是临时 (ephemeral) 端口 。通常是由那些不需要运行在预定义端口,而只是需要一些端口作为临时之需的服务使用。它们也是后面所要讲到的连接协商 (connection negotiation) 过程的一部分。选择该范围内的端口可能会对一些用户造成麻烦。除此之外,1025~48999 之间端口的使用是一视同仁的。如果你打算选用其中的一个作为服务器端口,那你应该看一下 IANA 的注册列表,确保你的选择不会和其他流行的服务器冲突。

require 'socket'

# 该套接字将会绑定在环回接口,只侦听来自本地主机的客户端。
local_socket = Socket.new(:INET, :STREAM)
local_addr = Socket.pack_sockaddr_in(4481, '127.0.0.1')
local_socket.bind(local_addr)

# 该套接字将会绑定在所有已知的接口,侦听所有向其发送信息的客户端。
any_socket = Socket.new(:INET, :STREAM)
any_addr = Socket.pack_sockaddr_in(4481, '0.0.0.0')
any_socket.bind(any_addr)

# 该套接字试图绑定到一个未知的接口,结果导致Errno::EADDRNOTAVAIL。
error_socket = Socket.new(:INET, :STREAM)
error_addr = Socket.pack_sockaddr_in(4481, '1.2.3.4')
error_socket.bind(error_addr)

发表评论