这是我所在组织的一位软件工程师提出的问题。我感兴趣的是最广义的定义。
当前回答
套接字= IP地址+端口(数字地址) 它们一起标识机器上网络连接的端点。(我刚刚是不是网络基础课不及格?)
其他回答
套接字地址是一个IP地址和端口号
123.132.213.231 # IP address
:1234 # port number
123.132.213.231:1234 # socket address
当两个套接字绑定在一起时,就发生了连接。
总结
TCP套接字是在特定TCP连接或监听状态的上下文中由IP地址和端口定义的端点实例。
端口是定义服务端点的虚拟化标识符(与服务实例端点又名会话标识符不同)。
TCP套接字不是一个连接,而是一个特定连接的端点。
可以存在到服务端点的并发连接,因为连接由其本地和远程端点标识,从而允许将流量路由到特定的服务实例。
对于给定的地址/端口组合,只能有一个侦听器套接字。
博览会
这是一个有趣的问题,它迫使我重新审视一些我自以为已经完全了解的东西。你可能会认为“插座”这样的名字是不言自明的:选择它显然是为了唤起你插入网线的端点的形象,有很强的功能相似之处。然而,在网络用语中,“套接字”这个词承载了如此多的负担,以至于有必要仔细地重新检查。
在最广泛的意义上,端口是一个入口或出口点。虽然不在网络环境中使用,但法语单词porte的字面意思是门或网关,进一步强调了端口是运输端点的事实,无论您运送数据还是大型钢铁集装箱。
为了本讨论的目的,我将只考虑TCP-IP网络的上下文。OSI模型非常好,但从未完全实现,更不用说在高流量、高压力条件下广泛部署。
IP地址和端口的组合严格地称为端点,有时称为套接字。这种用法起源于RFC793,即最初的TCP规范。
TCP连接由两个端点定义,也就是套接字。
端点(套接字)由网络地址和端口标识符的组合定义。请注意,address/port并不能完全标识一个套接字(稍后会详细介绍)。
端口的目的是区分给定网络地址上的多个端点。您可以说端口是一个虚拟端点。这种虚拟化使单个网络接口上的多个并发连接成为可能。
它是套接字对(4元组) 包括客户端IP地址, 客户端端口号,服务器IP地址, 和服务器端口号)指定 这两个端点唯一 对象中的每个TCP连接 互联网。(TCP-IP插图卷1,W. Richard Stevens)
在大多数c派生语言中,TCP连接是使用Socket类实例上的方法建立和操作的。虽然在更高的抽象级别上操作是常见的,通常是NetworkStream类的实例,但这通常会公开对套接字对象的引用。对于编码器来说,这个套接字对象似乎表示连接,因为连接是使用套接字对象的方法创建和操作的。
在c#中,要建立一个TCP连接(到一个现有的侦听器),首先要创建一个TcpClient。如果您没有指定TcpClient构造函数的端点,它将使用默认值—以某种方式定义本地端点。然后调用Connect 方法。此方法需要描述另一个端点的参数。
所有这些都有点令人困惑,并导致您相信套接字是一个连接,这是胡说八道。在理查德·多尔曼提出这个问题之前,我一直在这个误解中苦苦挣扎。
在进行了大量阅读和思考之后,我现在确信,使用带有两个参数LocalEndpoint和RemoteEndpoint的构造函数的类TcpConnection会更有意义。当本地端点的默认值是可接受的时,您可能会支持单个参数RemoteEndpoint。这在多址计算机上是不明确的,但是可以使用路由表通过选择到远程端点的最短路由的接口来解决这种不明确。
在其他方面,透明度也将得到提高。套接字不能通过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。
我认为哈格拉瓦尔的误解源于我对“认同”一词的谨慎使用。我的意思是“完全的,明确的,唯一的识别”。在上面的示例中,有两个端点的地址/端口组合为54.252.94.236:80。如果你只有地址和端口,你没有足够的信息来区分这些套接字。这些信息不足以识别套接字。
齿顶高
RFC793第2.7节第2段说
连接完全由两端的一对套接字指定。一个 本地套接字可能参与到不同外部的多个连接 套接字。
从编程的角度来看,socket的这个定义没有帮助,因为它与socket对象不同,后者是特定连接的端点。对于程序员(这个问题的大多数读者都是程序员)来说,这是一个至关重要的功能差异。
@plugwash提出了一个显著的观察。
最根本的问题是TCP RFC对socket的定义与所有主流操作系统和库所使用的socket的定义相冲突。
根据定义,RFC是正确的。当一个标准库误用术语时,它不会取代RFC。相反,它给该库的用户带来了一种责任负担,即理解两种解释,并小心用词和上下文。如果RFC不一致,则最新的和最直接适用的RFC优先。
参考文献
TCP-IP图解卷1协议,W. Richard Stevens, 1994 Addison Wesley RFC793,信息科学研究所,南加州大学DARPA RFC147,插座的定义,Joel M. Winett,林肯实验室
它们是来自两个不同领域的术语:“端口”是TCP/IP网络的概念,“套接字”是API(编程)的东西。“套接字”是通过将端口和主机名或网络适配器组合成一个数据结构(可以用来发送或接收数据)而形成的(在代码中)。
A socket is a communication endpoint. A socket is not directly related to the TCP/IP protocol family, it can be used with any protocol your system supports. The C socket API expects you to first get a blank socket object from the system that you can then either bind to a local socket address (to directly retrieve incoming traffic for connection-less protocols or to accept incoming connection requests for connection-oriented protocols) or that you can connect to a remote socket address (for either kind of protocol). You can even do both if you want to control both, the local socket address a socket is bound to and the remote socket address a socket is connected to. For connection-less protocols connecting a socket is even optional but if you don't do that, you'll have to also pass the destination address with every packet you want to send over the socket as how else would the socket know where to send this data to? Advantage is that you can use a single socket to send packets to different socket addresses. Once you have your socket configured and maybe even connected, consider it to be a bi-directional communication pipe. You can use it to pass data to some destination and some destination can use it to pass data back to you. What you write to a socket is send out and what has been received is available for reading.
Ports on the other hand are something that only certain protocols of the TCP/IP protocol stack have. TCP and UDP packets have ports. A port is just a simple number. The combination of source port and destination port identify a communication channel between two hosts. E.g. you may have a server that shall be both, a simple HTTP server and a simple FTP server. If now a packet arrives for the address of that server, how would it know if that is a packet for the HTTP or the FTP server? Well, it will know so as the HTTP server will run on port 80 and the FTP server on port 21, so if the packet arrives with a destination port 80, it is for the HTTP server and not for the FTP server. Also the packet has a source port since without such a source port, a server could only have one connection to one IP address at a time. The source port makes it possible for a server to distinguish otherwise identical connections: they all have the same destination port, e.g. port 80, the same destination IP (the IP of the server), and the same source IP, as they all come from the same client, but as they have different source ports, the server can distinguish them from each other. And when the server sends back replies, it will do so to the port the request came from, that way the client can also distinguish different replies it receives from the same server.
端口是网络协议用来访问连接的主机的实体。端口可以是特定于应用程序的,也可以是与特定通信媒介相关的。不同的协议使用不同的端口访问主机,如HTTP使用80端口或FTP使用23端口。您可以在应用程序中分配用户定义的端口号,但这些端口号应该大于1023。
端口打开到所需主机的连接,而套接字是网络间或进程间通信的端点。 套接字是由系统通过api(应用程序编程接口)分配的。
更微妙的区别是,当系统重新启动时,端口将出现,而套接字将被销毁。
推荐文章
- 我如何找到哪个程序正在使用端口80在Windows?
- 有效地测试Linux上的端口是否打开?
- 访问HTTP响应作为字符串在Go
- 在SSH会话中查找客户端的IP地址
- 模拟慢速互联网连接
- 127.0.0.1和localhost之间的区别是什么
- 为什么SCTP不常用/不为人所知
- 无法启动IIS Express Web服务器,注册URL失败,访问被拒绝
- 我可以在/etc/hosts中映射主机名*和端口*吗?
- 如何修改Play执行run命令时使用的默认端口(9000)?
- 连接网络共享时,如何提供用户名和密码
- 如何找到可用的端口?
- 如何通过windows命令行关闭TCP和UDP端口
- UDP和TCP比起来快多少?
- ssh -L转发多个端口