首页 文章

当服务器套接字接受客户端套接字时,究竟发生了什么?

提问于
浏览
6

我正在研究套接字编程,服务器套接字 accept() 令我困惑 . 我为服务器套接字 accept() 写了两个场景,请看一下:

  • 当服务器套接字执行 accept() 时,它会创建一个新的(客户端)套接字,该套接字从端口服务器套接字绑定到端口 different . 因此套接字通信是通过新绑定端口完成的,服务器套接字(仅适用于 accept() )正在等待原始绑定端口上的另一个客户端连接 .

我认为这不是很正确的答案,因为(1)端口匹配单个进程和(2)套接字接受是内部进程问题,单个进程可以有多个套接字 . 所以我根据一些stackoverflow答案做了第二个场景:

  • 当服务器套接字执行 accept() 时,它会创建一个新的(客户端)套接字 not 绑定到任何特定端口,当客户端与服务器通信时,它使用绑定到服务器套接字的 the port (谁 accept() 的连接)和 which client socket 来实际通信是通过传输级别的TCP头(?)来解决 (sourceIP, sourcePort, destIP, destPort) 元组(这也是可疑的,因为我认为socket是某种应用程序级对象)

这种情况也提出了一些问题 . 如果套接字通信仍然使用服务器套接字's port, i.e. client sends some messages to server socket port, doesn' t它使用服务器套接字的积压队列?我的意思是,如何区分来自客户的消息 connect()read() or write() ?如何解决服务器中的每个客户端套接字,没有任何端口绑定?

如果我的一个场景是正确的,会回答以下问题吗?或者我可能做了两个错误的场景,所以非常感谢你提供正确的答案,或至少一些相关的文本来研究 .

3 回答

  • 6

    当服务器套接字执行accept()时,它会创建一个新的(客户端)套接字,该套接字绑定到与端口服务器套接字绑定不同的端口 . 因此套接字通信是通过新绑定端口完成的,服务器套接字(仅适用于accept())正在等待最初绑定端口上的另一个客户端连接 .

    没有 .

    我认为这不是很正确的答案

    这是一个错误的答案 .

    因为(1)端口匹配单个进程

    这并不意味着任何相关的东西 .

    和(2)套接字接受是内部处理事务

    也不是这样 . 它实际上似乎没有任何意义 .

    和单个进程可以有多个套接字 .

    这是真的,但它与你的答案错误无关 . 您的答案错误的原因是因为没有使用第二个端口 .

    当服务器套接字执行accept()时,它会创建一个未绑定到任何特定端口的新(客户端)套接字

    不会 . 它创建了第二个套接字,它继承了服务器套接字中的所有内容:端口号,缓冲区大小,套接字选项,...除了文件描述符和LISTENING状态之外的所有内容,也许我忘记了其他内容 . 然后,它将套接字的远程IP:端口设置为客户端的端口,并将套接字置于ESTABLISHED状态 .

    当客户端与服务器通信时

    客户端已与服务器通信 . 这就是我们创建这个套接字的原因 .

    它使用绑定到服务器套接字的端口(谁接受()的连接)以及实际通信的客户端套接字通过传输级别的TCP头(?)来解析(sourceIP,sourcePort,destIP,destPort)元组

    这已经发生了 .

    这也是可疑的,因为我认为socket是某种应用程序级别的对象)

    不,不是 . 套接字是一个内核级对象,具有应用程序级文件描述符以标识它 .

    如果套接字通信仍然使用服务器套接字的端口,即客户端向服务器套接字端口发送一些消息,它是否使用服务器套接字的积压队列?

    否 . 积压队列用于传入连接请求,而不是数据 . 传入的数据进入套接字接收缓冲区 .

    我的意思是,如何在connect()和read()或write()之间区分来自客户端的消息?

    因为 connect() 请求在TCP头中设置了特殊位 . 它的最后部分可以与数据结合 .

    如何解决服务器中的每个客户端套接字,没有任何端口绑定?

    端口绑定发生在调用 accept() 时创建套接字的那一刻 . 你自己发明了这个难题 . 这不是真的 .

    如果我的一个场景是正确的,会回答以下问题吗?

    它们都不正确 .

    或者我可能犯了两个错误情景,所以非常感谢你提供正确的答案,或至少一些相关的文本来研究 .

    你肯定已经有相关的文本要学习吗?如果不这样做,您应阅读RFC 793或W.R. Stevens,TCP / IP Illustrated,第I卷,相关章节 . 你在这里有几个主要的误解 .

  • 6

    当你创建一个套接字并在该套接字上进行绑定然后监听时,你所拥有的就是所谓的 listening socket . Build 连接时,此套接字基本上克隆到新套接字,并且此套接字称为 the servicing socket ,它绑定的端口仍与原始端口相同 .

    但是这个套接字和之前的侦听套接字之间有一个重要的区别 . 即它是 socket pair 的一部分 . 唯一标识连接的是套接字对 . 因此图中有2个插座用于套接字对,TCP通信通道的两端有2个IP地址和2个端口 . 在克隆服务套接字期间,TCP内核将分配所谓的 TCB ,并在其中存储这2个IP @和2个端口 . TCB还包含属于TCB的套接字号 .

    每次进入TCP段时,都会检查TCP标头以及它是否是SYN,对于SYN,您将 Build 连接,以便您已经通过,但随后内核将通过其侦听套接字列表 . 如果它是普通的TCP数据包而不是SYN,则两个端口号都在TCP头中,并且IP @是IP头的一部分,因此使用此信息,内核能够找到属于此TCP连接的TCP . (对于SYN,此信息也存在,但正如我所说,对于SYN,您只需要处理侦听套接字)

    简而言之,它是如何运作的 .

    此信息可在UNIX网络编程中找到:套接字网络API . 在那里描述了到套接字的链接,而在其他参考材料中通常没有详细描述,而是通常突出显示TCP的细节 .

  • 0

    从Linux程序员手册,通过 man 2 accept 找到 . Link

    accept()系统调用与基于连接的套接字类型(SOCK_STREAM,SOCK_SEQPACKET)一起使用 . 它在侦听套接字sockfd的挂起连接队列上提取第一个连接请求,创建一个新的连接套接字,并返回一个引用该套接字的新文件描述符 . 新创建的套接字未处于侦听状态 . 原始套接字sockfd不受此调用的影响 .

    所以会发生什么是你有一个侦听TCP套接字 . 有人要求 connect() .

    然后你调用 accept() . 旧的侦听套接字仍处于侦听模式,而新的套接字则以连接模式创建 . 端口是原始侦听端口 .

    这不会干扰侦听套接字,因为新套接字不会侦听传入连接 .

相关问题