我正在研究套接字编程,而服务器套接字accept()
让我感到困惑。我为服务器套接字accept()
编写了两个方案,请看一下:
accept()
时,它会创建一个新的(客户端)套接字,该套接字绑定到端口服务器套接字绑定的不同的端口。因此套接字通信是通过新绑定端口完成的,服务器套接字(仅限accept()
)正在等待最初绑定端口上的另一个客户端连接。我认为这不是很正确的答案,因为(1)端口匹配单个进程,(2)套接字接受是进程内部事务,单个进程可以有多个套接字。所以我根据一些stackoverflow答案做了第二个场景:
accept()
时,它会创建一个不绑定到任何特定端口的新(客户端)套接字,当客户端与服务器通信时,它使用绑定到服务器套接字(谁accept()
的连接)和哪个客户端套接字实际通信的端口由TCP标头中的(sourceIP, sourcePort, destIP, destPort)
元组解析(? )在传输级别(这也是可疑的,因为我认为socket是某种应用程序级别的对象)这种情况也提出了一些问题。如果套接字通信仍然使用服务器套接字端口,即客户端向服务器套接字端口发送一些消息,它是否使用服务器套接字的积压队列?我的意思是,如何区分来自客户的消息connect()
和read() or write()
?如何解决服务器中的每个客户端套接字,没有任何端口绑定?
如果我的一个场景是正确的,会回答以下问题吗?或者我可能会制作两个错误的场景,所以非常感谢你提供正确的答案,或至少一些相关的文本来研究。
答案 0 :(得分:6)
当您创建套接字并在该套接字上执行绑定然后进行侦听时,您所拥有的就是所谓的listening socket
。
建立连接时,这个套接字基本上被克隆到一个新套接字,这个套接字被称为the servicing socket
,它所绑定的端口仍然与原始端口相同。
但是此套接字与之前的侦听套接字之间存在重要区别。即它是socket pair
的一部分。
唯一标识连接的是套接字对。因此图中有2个插座用于套接字对,TCP通信通道的两端有2个IP地址和2个端口。在克隆服务套接字期间,TCP内核将分配所谓的TCB
,并在其中存储这2个IP @和2个端口。 TCB还包含属于TCB的套接字号。
每次进入TCP段时,都会检查TCP标头是否为SYN,对于SYN,您将建立连接以便已经通过,但内核正在通过其监听列表插座。如果它是普通的TCP数据包而不是SYN,则两个端口号都在TCP头中,并且IP @是IP头的一部分,因此使用此信息,内核能够找到属于此TCP连接的TCP。 (对于SYN,此信息也存在,但正如我所说,对于SYN,您只需要处理侦听套接字)
简而言之,它是如何运作的。
此信息可在 UNIX网络编程:套接字网络API 中找到。在那里描述了与套接字的链接,而在其他参考资料中,通常没有详细描述,而是通常突出显示TCP的细节。
答案 1 :(得分: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卷,相关章节。你在这里有几个主要的误解。
答案 2 :(得分:1)
从Linux程序员手册中,通过man 2 accept
找到。 Link
accept()
系统调用与基于连接的套接字一起使用 类型(SOCK_STREAM,SOCK_SEQPACKET)。它提取第一个连接 请求侦听套接字的挂起连接队列, sockfd,创建一个新的连接套接字,并返回一个新文件 描述该套接字的描述符。新创建的套接字不是 在聆听状态。原始套接字sockfd不受影响 这个电话。
所以会发生的是你有一个侦听TCP套接字。有人要求connect()
。
然后拨打accept()
。旧的侦听套接字仍处于侦听模式,而新的套接字则以连接模式创建。端口是原始侦听端口。
这不会干扰侦听套接字,因为新套接字不会侦听传入连接。