Linux的Internet域套接字、传输协议(TCP/UDP)的套接字和端口

Linux的Internet域套接字、传输协议(TCP/UDP)的套接字和端口

长期以来,我一直被一些混乱的问题所困扰

  • Linux提供的互联网域套接字,
  • 传输协议(TCP/UDP)的套接字和
  • 传输协议 (TCP/UDP) 的端口。

SO 上一些相关帖子的回复有很多含糊之处和不一致之处,让我更加困惑。

  1. Linux 和传输协议(TCP/UDP)都有“套接字”的概念。这两个概念有何不同?是Linux提供的互联网域套接字(表示为文件?)(忠实地)实施传输协议中的套接字 (TCP/UDP)? (我想是的,如果这是真的,我们可以互换使用这两个术语。)

  2. 从概念上讲,这样的想法是否正确一个港口在传输协议 (TCP/UDP) 中作为元组(IP 地址、传输协议、端口号)或仅端口号? (我猜端口是一个元组(IP地址、传输协议、端口号),因为我已经多次被教育过,具有不同IP地址或不同传输协议的相同端口号代表不同的端口。从这个意义上说, 港口套接字(在传输协议中)似乎是一个相同的概念。)看来既定的名称“端口”仅意味着“端口号”,我将在下面明确使用“端口号”以避免不必要的混淆。

  3. 之间有什么关系套接字(在传输协议中)元组(IP 地址、传输协议、端口号)?套接字集和元组集(IP 地址、传输协议、端口号)之间是否存在双射映射?每个元组(IP 地址、传输协议、端口号)必须有一个或多个套接字,并且每个套接字必须有一个或多个元组(IP 地址、传输协议、端口号)吗?两个套接字可以共享相同的元组(IP 地址、传输协议、端口号)吗?两个元组(IP 地址、传输协议、端口号)可以共享同一个套接字吗?

  4. 我听说两个进程可以共享同一个套接字(我的理解是两个进程可以共享一个文件,假设Linux的互联网域套接字和传输协议(TCP/UDP)的套接字可以互换使用)。可以两个流程分享相同的元组(IP 地址、传输协议、端口号)

  5. 我听说两个连接不能共享同一个套接字(假设Linux的互联网域套接字和传输协议(TCP/UDP)的套接字可以互换使用)。可以两个连接分享相同的元组(IP 地址、传输协议、端口号)

谢谢。

答案1

  1. 套接字是操作系统的 API。此 API 允许相同或不同系统上的应用程序通过 TCP 和 UDP(以及其他)协议进行通信。 UNIX 域套接字(不是互联网您编写的域套接字)提供类似的功能,仅用于与同一系统上的应用程序进行通信。两者的概念相似:API 提供了创建套接字、绑定、侦听+接受和连接套接字、读取和写入套接字以及关闭套接字的方法。关于读取和写入,它们与与常规文件、命名管道、匿名管道等相关的其他文件描述符匹配,但文件描述符的创建不同,并且与常规文件相比,文件描述符上有更多的操作。
  2. TCP 和 UDP 中的端口号是 1 到 65535 之间的整数。“port”一词是“port number”的缩写。 IP地址和端口号以及协议的元组描述了端点地址。在阅读其他文献时,将其称为“端口”会引起混乱。
  3. 未连接(但已绑定)的套接字仅代表单个端点(ip、端口、协议)。一个连接的套接字代表一个本地端点和另一个(本地或远程)端点,即一个连接。同一连接不能有多个内核套接字,但同一个内核套接字可以有多个文件描述符。在多个连接的套接字中可以有相同的端点,但不能在同一个连接中具有相同的端点,即连接的另一个端点必须不同。实际上可以有多个代表同一端点的未连接套接字,但这是非常不寻常的。
  4. 套接字可以在进程之间共享,因为套接字是文件描述符,并且文件描述符可以共享。共享通常通过分叉来完成,即父级打开一些文件或套接字,子级继承它。但也有一些方法可以将文件描述符/套接字从一个进程发送到另一个进程。共享意味着两者都可以写入和读取,但不会重复数据,即如果父级读取某些数据,这些数据将从套接字获取,并且子级也无法读取。但是,一个进程不可能创建一个新套接字(而不是共享现有套接字),该新套接字表示与同一系统上现有套接字完全相同的连接。
  5. 两个套接字/连接可以在一个端点上共享相同的端口,但不能共享两个端点,即源IP、源端口、目标IP、目标端口或协议中的至少一项需要不同。

答案2

“端口”就像一栋房子,由城市、街道名称和门牌号来标识,“端口号”就像房子的门牌号。我希望这能帮助您理解我在帖子中的意思。

我懂了。我同意,这是一个值得思考的有用概念。

当我们需要谈论现有系统中的一些确切的技术细节时,“端口号”概念更容易定义。我们可以参考 TCP 数据包中端口字段的值,或者与 UNIX 套接字 API 一起使用sin_port的字段。struct sockaddr_in在这种类型的讨论中,我们可以让读者查阅有关如何使用 TCP 数据包的完整故事(也许在原始 RFC 中:-)。或者如何在程序中使用套接字 API 函数,也许可以通过查看man页面来了解。

这个概念被简化是很自然的。我们自然可以说“端口80”而不是“端口号80”。

原始 TCP 标准,RFC 793,讨论“端口”和“端口号”作为不同事物的概念。 (引言中也使用“端口标识符”来表示与“端口号”相同的意思)。

man例如,当前 Linux 上的页面并没有那么仔细地做出这种区分 。man 7 ip经常使用“port”作为“端口号”的缩写。

Linuxman页面是程序员参考的非常重要的文档,因此术语“端口”变得含糊不清。如果您担心可能会被误解,那么谈论“端口号”+ IP 地址是一个非常好的主意。

5.我听说两个连接不能共享同一个套接字(假设Linux的互联网域套接字和传输协议(TCP/UDP)的套接字可以互换使用)。两个连接可以共享相同的元组(IP 地址、传输协议、端口号)吗?

单个侦听端口可以接收来自多个不同源端口的连接。

在 Linux TCP 编程中,侦听器为每个此类连接获取一个套接字(并且正在侦听未连接的套接字)。

套接字 API 不提供任何相反的方法,即使用同一源端口建立多个传出连接。传输协议标准可能在技术上允许;我不知道。

请注意,如果您可以这样做,您将无法与同一目标端口建立多个连接。目标系统无法区分这两个连接。我猜他们觉得这个特定的限制太奇怪了,无法处理。然后,更广泛的限制被体现在原始 API 中,包括 UNIX 套接字。稍后,如果有人尝试这样做,他们将冒着在从未实际测试过的地方找到极端情况的风险:-)。

UDP 传输协议没有任何连接的概念,因此该问题不适用于它。如果您愿意,可以调用connect()UDP 套接字,但这只是为了方便。


如果你在现代文档中写“socket”,人们会将其解释为指UNIX套接字API中的套接字概念。 RFC 793 中“套接字”的定义有所不同。下面的定义是不是不再使用了。

为了允许单个主机内的多个进程同时使用 TCP 通信设施,TCP 在每个主机内提供了一组地址或端口。与互联网通信层的网络和主机地址连接起来,形成一个插座。一对套接字唯一地标识每个连接。也就是说,一个套接字可以同时用于多个连接。

相关内容