【问题标题】:What is a socket, physically?物理上的套接字是什么?
【发布时间】:2011-02-14 15:35:34
【问题描述】:

我总是更喜欢编程概念的物理意义而不是其逻辑意义。那么问题来了。

当我回顾套接字编程范例时,我注意到 bind()connect() 函数所做的就像 tuning socket() 函数创建的套接字。所以我猜 socket() 函数所做的只是创建一个数据结构(也可能是内核空间中的一个数据结构)来保存 有关端到端通信的详细信息客户端和服务器之间的设置。而 bind(), connect() 只需填写那个数据结构。

我不熟悉socket API的实现,希望有人能解决我的问题。

【问题讨论】:

  • 这是你眼球所在的颅骨上的洞。哦,你说的是另一种插座吗?没关系...
  • “头骨”是胸部和躯干上方的身体部分。它容纳了大脑。眼窝是面部容纳眼睛的两个开口。他在开玩笑。
  • 你在这个问题上付出了很多,但 San Jacinto 为你提供了一个链接,指向 Linux 系统的 IP 堆栈的实际实现,我已经解释了在物理上放置了什么wire 对应于传递给这些函数的内容,我们都解释了实现细节会因系统而异。如果这些都不是您正在寻找的东西,也许您应该添加更多关于您正在寻找的东西的详细信息。
  • @BoltClock 物理上,而不是生理上 ;)
  • 你似乎不知道“身体”是什么意思。从物理上讲,它根本不存在,除了可能由电线上的一些电子表示。这就是为什么你得到开玩笑的回应。从逻辑上讲,您在下面有详细的答案。

标签: sockets network-programming


【解决方案1】:

这是高度依赖于平台的。 API 的重点是让您无需了解这些详细信息。

如果你真的有兴趣学习这个(你不应该只学习应用程序和系统应用程序编程),你可以从 kernel.org 下载一个 linux 内核源代码存档,并通过查看下面的内容来检查 Linux 的 TCP/IP 实现网络/ipv4

为了增加一些清晰度,

为了通过网络传输数据,我们通常遵守国际标准化组织定义的标准。他们有一个称为 OSI 或开放系统互连模型的标准。

此模型为应用程序定义了 7 个抽象层,以便在网络中移动数据。我只讨论前 4 个,因为它们与您的问题相关。

物理层:

这一层定义了数据在媒体上的实际传输方式。硬件供应商遵守关于如何移动数据的既定标准。这些标准就电信号和数据移动的电子方面达成一致。

如何融入系统:

希望这一层几乎不需要软件支持。此处进行的任何编程都可能在模块上完成,而不是在内核或应用程序中完成。

数据链路层:

这是可以说涉及某种编程的第一层。这一层定义了在物理链路上运行的线路级协议。以太网是一种协议。帧中继是另一个。令牌环是另一个。链路的每一端都必须运行相同的数据链路协议。该层结合了兼容的物理层标准,提供了一种将数据从一台主机实际传输到另一台主机的方法。在许多方面,它可以被认为是物理层的附录,而不是它自己的层,但是因为这里定义了链路级协议,所以这不是一个很好的类比。该层为网络上的节点提供物理地址。

如何融入系统:

您需要编写一个驱动程序来与运行这些数据链路协议的接口模块通信。根据模块和系统,模块可能拥有实际工作所需的一切,或者可能需要一些系统级帮助。理想情况下,您只需创建一组代码接口(可能实现为包含用于适当处理 I/O 的函数指针的结构。我真的不知道),当您安装新的物理模块时,驱动程序只需要实现这些代码接口,现在你的物理模块就可以使用了。

网络层

这是提供在网络之间移动数据的能力的层(在 TCP/IP 的情况下)。 Internet 协议在这一层定义。该层为节点提供逻辑地址,以便将它们分组到网络中。通过了解主机所在的网络(也称为子网,使用子网掩码以编程方式确定),我们运行的算法可以正确地将数据从一个网络移动到另一个网络。如果一台主机在中国的网络 A 上,而一台主机在澳大利亚的网络 B 上,则此级别的算法负责提供连接这些网络和这些主机的路径。

为这一层编程的重要一点是,您应该能够“插入”任何数据链路层以进行传输。这意味着一旦您在系统上创建代码以通过以太网、令牌环、3G 或帧中继进行传输,您应该能够使用所有这些代码,而无需网络层知道它使用的是什么数据链路技术。在网络之间移动数据的逻辑不应依赖于它所运行的实际物理链路。

这一层将您的数据放入数据包中,数据包是通过互联网路由的。

如何融入系统:

所有这一层都必须作为系统的一部分进行编码。它完全是一个软件结构,应该尽可能地与数据链路层隔离。在实践中,我还不足以说这是如何完成的。因为这一层的功能是系统定义的,所以我们可以完全控制软件必须支持的内容。与数据链路层相比,这使得允许高层协议使用该层的代码接口的构造变得相当简单。

传输层:

这一层定义了数据的分段(因为如果您只是一次发送大量数据,几乎没有任何东西可以按顺序发送)。这一层还定义了 TCP,它提供握手、校验和、数据包排序、可变数据窗口大小和保证可靠性。 TCP 使您能够在同一物理链路上创建多个逻辑通信通道。它将链接上的一个报道与同一链接上的另一个对话区分开来。 UDP也是在这一层定义的,可以认为是一个非常轻量级的TCP。 UDP 几乎没有提供 TCP 的任何好处,但仍然提供物理通道复用。

如果你的传输层写得很好,你的应用程序就不需要(从代码架构的角度来说)担心传输层是使用 TCP 还是 UDP(只提这两个最流行的 b/c知识产权)。虽然您可以根据时序性能需求或可靠性需求来选择其中一个(实际上,应用程序通常会假设它们正在运行哪一个),但您的应用程序不需要确切知道哪个正在运行。

因为这一层是建立在网络层之上的,所以如果我们的数据在不同的网络上,我们不需要担心我们的数据将如何从一台主机传输到另一台主机。如果路由器正在运行标准路由协议,并通过一些静态定义的路由进行扩充,我们无需担心。这一切都由网络层为我们处理。如果我们正在运行的主机上的网络层配置发生变化,那也没关系。我们无需更改整个应用程序即可解决此问题。

如何融入系统:

与网络层非常相似,只是它提供的功能与网络层不同。此外,与网络层接口相比,这些接口更多地用于用户空间。这是实际定义您在 TCP/IP 网络中使用的套接字的层。


希望这会有所帮助,并且您可以理解为什么您的问题对我们大多数人来说有点困惑。

【讨论】:

  • 有时候程序员只是好奇。
  • @the_drow 毫无疑问。与其说是“不要看这里!!”,不如说是对不要依赖此类结构的警告。事物的类型。
  • 链接失效了。
  • 上面的描述仍然没有解释物理领域中的“套接字”到底是什么。您能否更新以在此基础上再添加几行代码。
【解决方案2】:

您熟悉OSI model 吗? bind() 指定要使用的本地 IP 地址和端口(第 4 层),因此当数据包物理发出时,它指定该 IP 地址作为发送方,connect() 指定要物理放置的远程 IP 地址和端口那些数据包。

顺便说一句,很多编程都是纯粹的“逻辑”,并没有真正的“物理”含义,除非“物理”实际上是指“实现细节”,这会因平台而异。如果您实际上是在询问物理实现意味着如何将“意义”转换为电信号,那么作为计算机工程师可能会比作为程序员更快乐。

【讨论】:

  • 熟悉 OSI 模型吗? TCP/UDP 端口号根本不属于第 3 层。
  • @PavelŠimerda,谢谢修复。已经好几年了,所以我不确定这只是一个错字还是什么。
【解决方案3】:

我的 2 美分价值:

一个socket基本上是一个源IP、源端口、目的IP和目的端口一致的。 (从物理上讲,它真的什么都不是,这是一个基于软件的概念)这样操作系统可以判断哪个应用程序(通过它的端口号)需要接收数据包或发送数据包。

网络堆栈(TCP/IP 或 OSI 模型)的实现方式因您的操作系统而异。如果您想了解更多信息包是如何传输和处理的,请研究 OSI 模型或 TCP/IP 堆栈。这将告诉您信息在离开您的应用程序以通过网络发送时会发生什么。

操作系统负责处理数据包,所以如果您是程序员,如前所述,您通常对这些细节不感兴趣。

如果您像我一样好奇并想知道,我建议您开始阅读。 :)

【讨论】:

  • 连接的套接字是 4 个元组,但通用的“套接字”不一定。听起来您主要是根据 TCP 来考虑,在这种情况下,这里的一切都是正确的——也许除了 TCP 确实指定了几个不应因系统而变化的参数。 (当然,这不是我的反对意见,但也许他们是按照这些思路思考的?)
猜你喜欢
  • 2021-12-06
  • 2010-12-16
  • 2014-04-26
  • 2013-01-24
  • 2017-01-25
  • 2012-06-11
  • 2021-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多