我对端口的实际用途及其工作原理有相当的了解。不过,我有几个问题想澄清一下。
- 如果我们发送请求时没有指定服务器套接字的端口,会发生什么情况?
- 有没有办法设置一台机器,这样就不用让一个进程监听某个特定端口,而是让同一个进程处理发送到我的 IP 地址的所有请求?在这种情况下,客户端可以省略请求中的端口。
- 从问题 2 开始,如果我只想在 Raspberry Pi 之类的东西上运行某种服务器,我是否可以让我的 IP 地址路由到我的 RPi,它使用同一台服务器处理所有传入的网络请求?也就是说,人们只需连接到 IP 地址(无端口号)即可连接到我的服务器。
答案1
为什么发送请求时除了 IP 还必须提供端口号?
因为 TCP(和 UDP)协议需要它。它是协议规范的一部分。
如果我们发送请求时没有指定服务器套接字的端口,会发生什么情况?
嗯,如果您不指定端口号,API 调用的该部分可能会出现零。端口 0 是保留端口,某些实现使用它来表示端口由系统动态分配。
有没有办法设置一台机器,这样不是让一个进程监听特定的端口,而是让所有发送到我的 IP 地址的请求都由同一个进程处理?
如果你使用 TCP 或 UDP 传输层协议或任何基于它们构建的应用程序级协议,则不会。例如 HTTP
在某些操作系统中,单个进程作为操作系统的一部分,但它将连接转交给特定的应用程序。
我可以将它设置为我的 IP 地址路由到我的 RPi
你可以配置路由器将所有传入的连接请求路由到你的树莓派
人们只需连接 IP 地址,无需端口号,即可连接到我的服务器。
不使用 HTTP 等标准协议。
我认为使用标准 API(如 Berkely Sockets)是不可能的。我想您可以花点功夫使用自己设计的不同或新的传输层协议。您需要一些非常充分的理由才能克服所有不便之处。
答案2
如果我们发送请求时没有指定服务器套接字的端口,会发生什么情况?
不能,套接字按定义就是 IP + 端口。端口存在的原因是因为一台机器上的多个程序可以发送/接收流量,端口用于区分两端的进程。
有没有办法设置一台机器,这样不是让一个进程监听特定的端口,而是让所有发送到我的 IP 地址的请求都由同一个进程处理?
您可以让您的进程打开 65535 个套接字,每个端口一个。如果没有某种奇怪的中间程序(您可能必须自己编写),您无法让现有程序执行此操作(该程序不是为此编写的)。
在 Linux 上,您可能能够创建iptables
执行此操作的配置,或执行等效操作。
如果我只想在 Raspberry Pi 之类的东西上运行某种服务器,我可以让我的 IP 地址路由到我的 RPi,然后使用同一个服务器处理所有传入的网络请求吗?
大多数标准家用路由器的默认情况是忽略外部人员发送的任何流量。
在几乎所有此类路由器上,您都可以进行端口转发,即告诉路由器将特定端口上的传入流量转发到路由器后面的私有网络上的特定系统。
您可能还会告诉路由器将任何未经请求的传入流量转发到路由器后面的专用网络上的特定 IP。这称为 DMZ。
答案3
端口对于允许多个进程在服务器之间进行通信的协议至关重要。这不仅仅是一个实际的考虑。
知名服务已分配端口:DNS=53、HTTP=80、HTTPS=443、SMTP=25、Telnet=23、SSH=22、FTP=20&21 等。对于此类知名服务,如果它们在分配给服务的端口上运行,则无需指定端口。在 Unix/Linux 平台上,分配的端口列在 /etc/services 中。
- 对于 TCP 和 UDP,没有端口就无法建立连接。标头包含源端口和目标端口的字段。这些字段中始终会有一个值,即使该值是零。
- 可以捕获到达某个接口的所有数据包。这就是 tcpdump 等工具的工作原理。
- 如 1 中所述,所有传入请求都会有一个端口号。SOHO 路由器通常支持 DMZ,并将所有未路由的传入请求转发到分配给 DMZ 的 IP 地址。在大多数情况下,您只需将服务所需的端口转发到服务器(您的 Raspberry Pi)。这将允许您拥有多个运行不同服务的 Raspberry Pi。