networking - 端口和套接字有什么区别?

标签 networking sockets port

这是我组织中的一位软件工程师提出的问题。我对最广泛的定义感兴趣。

最佳答案

概括
TCP 套接字是端点实例 在特定 TCP 连接或监听状态的上下文中由 IP 地址和端口定义。
端口是虚拟化标识符 定义服务端点(不同于服务实例端点又名 session 标识符)。
TCP 套接字不是连接 ,它是特定连接的端点。
可以有到服务端点的并发连接 ,因为连接由其本地和远程端点标识,允许将流量路由到特定服务实例。
对于给定的地址/端口组合,只能有一个监听器套接字 .
博览会
这是一个有趣的问题,它迫使我重新审视一些我认为自己完全了解的事情。您会认为像“socket”这样的名称不言自明:显然选择它是为了唤起您将网络电缆插入的端点的图像,它们具有很强的功能相似性。然而,在网络用语中,“套接字”这个词承载了太多的包袱,需要仔细重新检查。
在最广泛的意义上,端口是入口或导出点。尽管未在网络上下文中使用,法语单词 porte 的字面意思是门或网关,进一步强调了无论您运送数据还是大型钢制容器,端口都是运输端点的事实。
出于本次讨论的目的,我将只考虑 TCP-IP 网络的上下文。 OSI 模型都非常好,但从未完全实现,更不用说在高流量高压力条件下广泛部署。
IP 地址和端口的组合严格称为端点,有时也称为套接字。这种用法起源于 RFC793,原始 TCP 规范。
TCP 连接由两个端点(即套接字)定义。
端点(套接字)由网络地址和端口标识符的组合定义。请注意,地址/端口并不能完全识别套接字(稍后会详细介绍)。
端口的目的是区分给定网络地址上的多个端点。你可以说一个端口是一个虚拟化的端点。这种虚拟化使单个网络接口(interface)上的多个并发连接成为可能。

It is the socket pair (the 4-tuple consisting of the client IP address, client port number, server IP address, and server port number) that specifies the two endpoints that uniquely identifies each TCP connection in an internet. (TCP-IP Illustrated Volume 1, W. Richard Stevens)


在大多数 C 派生语言中,TCP 连接是使用 Socket 类实例上的方法建立和操作的。尽管通常在更高级别的抽象上进行操作,通常是 NetworkStream 类的实例,但这通常会公开对套接字对象的引用。对于编码人员来说,这个套接字对象似乎代表了连接,因为连接是使用套接字对象的方法创建和操作的。
在 C# 中,要建立 TCP 连接(到现有监听器),首先要创建一个 TcpClient。如果您没有为 TcpClient 构造函数指定端点,则它使用默认值 - 以一种或另一种方式定义本地端点。然后调用 Connect
您创建的实例上的方法。此方法需要一个描述另一个端点的参数。
所有这些都有些令人困惑,并让您相信套接字是一种连接,这是胡说八道。在理查德·多曼提出这个问题之前,我一直在这种误解下工作。
在进行了大量阅读和思考之后,我现在确信拥有一个带有两个参数(LocalEndpoint 和 RemoteEndpoint)的构造函数的类 TcpConnection 会更有意义。当本地端点可以接受默认值时,您可能会支持单个参数 RemoteEndpoint。这在多宿主计算机上是不明确的,但是可以使用路由表通过选择具有到远程端点的最短路由的接口(interface)来解决歧义。
其他方面的清晰度也会得到提高。一个套接字不是通过 IP 地址和端口的组合来识别的:

[...]TCP demultiplexes incoming segments using all four values that comprise the local and foreign addresses: destination IP address, destination port number, source IP address, and source port number. TCP cannot determine which process gets an incoming segment by looking at the destination port only. Also, the only one of the [various] endpoints at [a given port number] that will receive incoming connection requests is the one in the listen state. (p255, TCP-IP Illustrated Volume 1, W. Richard Stevens)


如您所见,网络服务不仅有可能而且很可能拥有多个具有相同地址/端口的套接字,但在特定地址/端口组合上只有一个监听器套接字。典型的库实现提供了一个套接字类,它的一个实例用于创建和管理连接。这是非常不幸的,因为它引起了混淆,并导致了这两个概念的广泛混淆。
Hagrawal 不相信我(见评论)所以这里有一个真实的样本。我将网络浏览器连接到 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 .
我认为 Hagrawal 的误解源于我非常谨慎地使用“识别”这个词。我的意思是“完全、明确和唯一标识”。在上面的示例中,有两个端点的地址/端口组合 54.252.94.236:80 .如果您只有地址和端口,则没有足够的信息来区分这些套接字。没有足够的信息来识别套接字。
附录
RFC793 第 2.7 节的第二段说

A connection is fully specified by the pair of sockets at the ends. A local socket may participate in many connections to different foreign sockets.


从编程的角度来看,socket 的这个定义没有帮助,因为它与 socket 对象不同,socket 对象是特定连接的端点。对于程序员来说,这个问题的大多数听众都是程序员,这是一个至关重要的功能差异。
@plugwash 做了一个突出的观察。

The fundamental problem is that the TCP RFC definition of socket is in conflict with the defintion of socket used by all major operating systems and libraries.


根据定义,RFC 是正确的。当图书馆滥用术语时,这不会取代 RFC。取而代之的是,它给图书馆的用户带来了理解两种解释并注意单词和上下文的责任。如果 RFC 不同意,则以最新且最直接适用的 RFC 为准。
引用
  • TCP-IP Illustrated Volume 1 The Protocols,W. Richard Stevens,1994 Addison Wesley
  • RFC793 , 南加州大学 DARPA 信息科学研究所
  • RFC147 , 套接字的定义, Joel M. Winett, Lincoln Laboratory
  • 关于networking - 端口和套接字有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/152457/

    相关文章:

    java - Openshift 使用 JBoss EAP 连接到套接字

    networking - 如何在命名空间中创建 SSH 服务器?

    python - 通过 socket.sendto() 发送附加参数

    c++ - 内存/线程泄漏,使用 WinSock2 开发简单的 HTTP 服务器

    javascript - 套接字 io 发射生成 'instanceof' 的右侧不是对象

    java - 如何在 Java 中使用 SocketServer 来阻止正在使用的端口?

    C# 3.5 - 跨网络连接命名管道

    networking - WireShark轻量级抓包,能做到吗?

    linux - 给定一个已建立的从客户端到服务器的 tcp 连接,第二个是否在没有服务器显式调用 accept 的情况下得到解决?

    apache - 通过 Apache 服务页面访问 socket.io 服务器