Summary
TCP 套接字是一个端点instance由特定 TCP 连接或侦听状态上下文中的 IP 地址和端口定义。
端口是虚拟化标识符定义服务端点(与服务不同)instance端点又名会话标识符)。
TCP 套接字是not一个连接,它是特定连接的端点。
可以有到服务端点的并发连接,因为连接是由本地和远程端点,允许将流量路由到特定的服务实例。
对于给定的地址/端口组合只能有一个侦听器套接字.
博览会
这是一个有趣的问题,迫使我重新审视一些我自以为已经了解透彻的事情。您可能会认为像“套接字”这样的名称是不言自明的:选择它显然是为了唤起您插入网络电缆的端点的图像,两者在功能上有很强的相似之处。然而,在网络用语中,“套接字”这个词带有太多的包袱,因此有必要仔细重新检查。
从最广泛的意义上讲,端口是入口或出口点。尽管没有在网络环境中使用,但法语单词porte字面意思是门或网关,进一步强调了这样一个事实:无论您运输数据还是大型钢制集装箱,港口都是运输端点。
为了讨论的目的,我将限制对 TCP-IP 网络环境的考虑。 OSI 模型一切都很好,但从未完全实施,更不用说在高流量高压力条件下广泛部署。
IP 地址和端口的组合严格称为端点,有时也称为套接字。这种用法源自 RFC793,即原始 TCP 规范。
A TCP 联系由两个端点定义sockets.
端点(套接字)由网络地址和地址的组合定义port标识符。请注意,地址/端口确实not完全识别一个套接字(稍后会详细介绍)。
端口的目的是区分给定网络地址上的多个端点。您可以说端口是虚拟化端点。这种虚拟化使得单个网络接口上的多个并发连接成为可能。
它是套接字对(4元组
由客户端 IP 地址组成,
客户端端口号、服务器IP地址、
和服务器端口号)指定
唯一的两个端点
标识每个 TCP 连接
互联网。 (TCP-IP 图解卷 1,W·理查德·史蒂文斯)
在大多数 C 派生语言中,TCP 连接是使用 Socket 类实例上的方法来建立和操作的。尽管在更高的抽象级别(通常是 NetworkStream 类的实例)上进行操作很常见,但这通常会公开对套接字对象的引用。对于编码人员来说,此套接字对象似乎代表连接,因为连接是使用套接字对象的方法创建和操作的。
在 C# 中,要建立 TCP 连接(到现有侦听器),首先需要创建一个TCP客户端。如果您没有指定端点TCP客户端它使用默认值的构造函数 - 定义本地端点的一种方式或另一种方式。然后你调用Connect您创建的实例上的方法。此方法需要一个描述另一个端点的参数。
所有这些都有点令人困惑,让您相信套接字就是一个连接,这完全是胡说八道。我一直在这种误解中挣扎,直到理查德·多尔曼提出这个问题。
经过大量阅读和思考后,我现在确信开设课程更有意义TCP连接使用带有两个参数的构造函数,本地端点 and 远程端点。你可能可以支持一个论点远程端点当本地端点可以接受默认值时。这在多宿主计算机上是不明确的,但是可以使用路由表通过选择具有到远程端点的最短路由的接口来解决不明确性。
其他方面的清晰度也将得到提高。一个插座是not通过IP地址和端口的组合来识别:
TCP 使用构成本地和外部地址的所有四个值来解复用传入数据段:目标 IP 地址、目标端口号、源 IP 地址和源端口号。 TCP 无法仅通过查看目标端口来确定哪个进程获取传入数据段。此外,[给定端口号] 处的[各种] 端点中唯一一个将接收传入连接请求的端点是处于侦听状态的端点。 (第255页,TCP-IP 图解卷 1,W·理查德·史蒂文斯)
正如您所看到的,网络服务不仅有可能而且很可能拥有多个具有相同地址/端口的套接字,但在特定地址/端口组合上只有一个侦听器套接字。典型的库实现提供一个套接字类,该类的实例用于创建和管理连接。这是非常不幸的,因为它引起混乱并导致这两个概念广泛混淆。
Hagrawal 不相信我(请参阅评论),所以这是一个真实的示例。我连接了网络浏览器http://dilbert.com http://dilbert.com然后跑了netstat -an -p tcp
。输出的最后六行包含两个示例,说明地址和端口不足以唯一标识套接字。 192.168.1.3(我的工作站)和 54.252.94.236:80(远程 HTTP 服务器)之间有两个不同的连接
TCP 192.168.1.3:63240 54.252.94.236:80 SYN_SENT
TCP 192.168.1.3:63241 54.252.94.236:80 SYN_SENT
TCP 192.168.1.3:63242 207.38.110.62:80 SYN_SENT
TCP 192.168.1.3:63243 207.38.110.62:80 SYN_SENT
TCP 192.168.1.3:64161 65.54.225.168:443 ESTABLISHED
由于套接字是连接的端点,因此有两个具有地址/端口组合的套接字207.38.110.62:80
还有两个带有地址/端口组合54.252.94.236:80
.
我认为哈格拉瓦尔的误解源于我非常小心地使用“识别”这个词。我的意思是“完全、明确且唯一地标识”。在上面的示例中,有两个具有地址/端口组合的端点54.252.94.236:80
。如果您只有地址和端口,则没有足够的信息来区分这些套接字。信息不够identify一个插座。
Addendum
RFC793 第 2.7 节第二段说
连接完全由末端的一对套接字指定。 A
本地套接字可能会参与到不同外部的许多连接
插座。
从编程角度来看,套接字的这种定义没有帮助,因为它与套接字不同object,这是特定连接的端点。对于程序员来说,这个问题的大多数受众都是程序员,这是一个至关重要的功能差异。
@plugwash 提出了一个重要的观察。
根本问题是 TCP RFC 对套接字的定义与所有主要操作系统和库使用的套接字定义相冲突。
根据定义,RFC 是正确的。当库误用术语时,这不会取代 RFC。相反,它给该库的用户带来了理解两种解释并注意单词和上下文的责任负担。如果 RFC 不一致,则以最新且最直接适用的 RFC 为准。
参考
-
TCP-IP 图解卷 1 协议,W.理查德·史蒂文斯,1994 年艾迪生·韦斯利
-
RFC793 https://www.rfc-editor.org/rfc/rfc793,南加州大学 DARPA 信息科学研究所
-
RFC147 https://www.rfc-editor.org/rfc/rfc147, 套接字的定义,Joel M. Winett,林肯实验室