代码之家  ›  专栏  ›  技术社区  ›  Eli Bendersky

套接字API accept()函数是如何工作的?

  •  143
  • Eli Bendersky  · 技术社区  · 16 年前

    套接字API是TCP/IP和UDP/IP通信(即我们所知的网络代码)的实际标准。然而其核心功能之一, accept() 有点神奇。

    借用半形式化的定义:

    accept()在服务器端使用。 它接受收到的传入尝试 从以下位置创建新的TCP连接 远程客户端,并创建一个新的 与套接字关联的套接字 此连接的地址对。

    换言之, accept 返回一个新的套接字,服务器可以通过该套接字与新连接的客户端通信。旧插座(上面 接受 被调用)保持打开,在同一端口上,监听新连接。

    如何 接受 工作?它是如何实施的?关于这个话题有很多困惑。许多人声称accept打开了一个新端口,您可以通过它与客户端通信。但这显然不是真的,因为没有打开新端口。您实际上可以通过同一端口与不同的客户端通信,但如何实现呢?当多个线程调用时 recv 在同一个端口上,数据如何知道去哪里?

    我想这是客户端的地址与套接字描述符相关联,每当数据通过时 recv 它被路由到正确的插座,但我不确定。

    若能深入了解此机制的内部运作,那将十分有益。

    4 回复  |  直到 16 年前
        1
  •  118
  •   Stefan van den Akker Raymond Hettinger    6 年前

    你的困惑在于认为套接字是由服务器IP标识的:服务器端口。实际上,套接字是由四个信息唯一标识的:

    Client IP : Client Port Server IP : Server Port

    因此,虽然服务器IP和服务器端口在所有接受的连接中都是恒定的,但客户端信息使其能够跟踪所有内容的去向。

    举例说明:

    假设我们有一台服务器 192.168.1.1:80 以及两个客户端, 10.0.0.1 10.0.0.2 .

    10.0.0.1 在本地端口上打开连接 1234 并连接到服务器。现在服务器有一个套接字,标识如下:

    10.0.0.1:1234 - 192.168.1.1:80  
    

    现在 10.0.0.2 在本地端口上打开连接 5678 并连接到服务器。现在服务器有两个套接字,标识如下:

    10.0.0.1:1234 - 192.168.1.1:80  
    10.0.0.2:5678 - 192.168.1.1:80
    
        2
  •  60
  •   Methos    10 年前

    只是为了补充用户“17 of 26”给出的答案

    套接字实际上由5个元组组成-(源ip、源端口、目标ip、目标端口、协议)。这里的协议可以是TCP、UDP或任何传输层协议。此协议在IP数据报中的“协议”字段的数据包中标识。

    因此,服务器上的不同应用程序可以在完全相同的4元组上与同一客户端通信,但协议字段不同。例如

    服务器端的Apache正在进行对话(TCP上的server1.com:880-client1:1234) 和 魔兽世界对话(UDP上的server1.com:880-client1:1234)

    即使所有其他4个字段都相同,客户端和服务器都会处理这一点,因为在这两种情况下,IP数据包中的协议字段是不同的。

        3
  •  8
  •   a2800276    16 年前

    当我学习这个时,让我困惑的是这些术语 socket port 这表明它们是物理的,而事实上它们只是内核用来抽象网络细节的数据结构。

    因此,数据结构被实现为能够区分来自不同客户端的连接。至于 怎样 实现了它们,答案要么是a。)没关系,套接字API的目的正是实现不重要,要么是b。)看看就知道了。除了强烈推荐的Stevens书籍提供了一个实现的详细描述外,还可以查看Linux、Solaris或BSD中的源代码。

        4
  •  0
  •   John R Strohm    16 年前

    正如另一个人所说,套接字由4个元组(客户端IP、客户端端口、服务器IP、服务器端口)唯一标识。

    在服务器IP上运行的服务器进程维护一个活动套接字的数据库(这意味着我不在乎它使用什么样的表/列表/树/数组/魔术数据结构),并在服务器端口上监听。当它收到消息时(通过服务器的TCP/IP堆栈),它会根据数据库检查客户端IP和端口。如果在数据库条目中找到客户端IP和客户端端口,则将消息传递给现有的处理程序,否则将创建一个新的数据库条目并生成一个新处理程序来处理该套接字。

    在ARPAnet的早期,某些协议(例如FTP)会监听指定端口的连接请求,并用切换端口进行回复。该连接的进一步通信将通过切换端口进行。这样做是为了提高每个数据包的性能:当时计算机的速度要慢几个数量级。

    推荐文章