accept() 函数是如何工作的?

Posted

技术标签:

【中文标题】accept() 函数是如何工作的?【英文标题】:How does the accept() function work? 【发布时间】:2017-05-21 15:09:16 【问题描述】:

我对 C 中的 accept() 函数有疑问。

当服务器接收到连接时,accept() 函数会创建一个新的套接字与客户端通信,然后让“旧套接字”监听新的连接。

那么,我知道服务器可以通过“新套接字”与客户端通信,但是客户端如何与“新套接字”通信(因为客户端不知道这个“新套接字”)?

【问题讨论】:

客户端在服务器用socket()知道它之前创建了“新套接字”,并用connect()将它指向服务器。注意:二进制“socket ID”代表不同物理机上不同进程的不同内存位置。 客户端也不知道 old 套接字。 【参考方案1】:

套接字是网络编程 API 的抽象。在线上和客户端仍然只有一个连接,客户端看不到服务器是否正在使用带有监听、接受等的网络 API,或者服务器是否正在使用其他 API 或原始套接字来建立连接。

【讨论】:

【参考方案2】:

在服务器端,监听socket只关联一个本地IP和端口,处于LISTEN状态。

相比之下,服务器上接受的套接字(以及客户端上连接的套接字)由本地 IP 和端口以及远程 IP 和端口标识,并处于 ESTABLISHED 状态。

在客户端,服务器使用与连接的套接字分开的侦听套接字并不重要。当客户端从connect返回时,服务端已经从accept返回,各自返回的socket描述符可以相互通信了。

【讨论】:

那么服务器中的多个套接字是否有可能在同一个本地端口上运行?它们是通过远程地址和端口来区分的吗? @Milack 没错。一个监听套接字可以多次调用accept 来接受多个连接。所有这些接受的套接字都将具有相同的本地 IP 和端口,但远程 IP 和/或端口会有所不同。 好的,我明白了。但是,在 connect()(在套接字“sock”上)返回之后,如果客户端在同一个套接字(“sock”)上写了一些东西,客户端接受的套接字和“新套接字”之间的“链接”是如何完成的" 用 accept() 创建?我的意思是,客户端如何自动在使用 accept() 创建的套接字上写入? @Masiwan 客户端连接的套接字与远程 IP 和端口(即它连接的那个)以及本地 IP 和端口相关联。因此,当客户端执行send 时,它会发送到关联的远程 IP:端口。在接受的套接字的服务器端也是如此。 @dbush 所以,如果我理解的话,在 connect() 调用之前,客户端的套接字没有与远程 IP/端口相关联,但是在 connect() 返回之后(然后是 accept() return),客户端的socket是关联的?【参考方案3】:

解释是 TCP(TCP/IP 传输中的端点)由一对 IPaddress/port_number 唯一标识。当客户端请求连接时,它使用其 IP 和端口号,这是唯一的一对。该操作将 SRCIP+SRCPORT 绑定到 DSTIP+DSTPORT,这 4 个数字(两个 IP 加上两个端口)唯一标识一个连接。所以服务器上的两个套接字实际上是指两个不同的连接/流。

【讨论】:

【参考方案4】:

IP 协议(​​包括 TCP/IP)中的任何通信都发生在两个端点之间。端点始终是主机:端口。在 TCP 世界中,两个端点标识连接。套接字与连接相关联,而不是与端点相关联。

因此,您可以从 2 个 accept() 调用返回 2 个套接字,描述 2 个不同的连接。

这是一个在 unix 机器上输出 netstat -an 的示例:

tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN
tcp        0      0 170.44.26.7:22              161.231.133.178:11550       ESTABLISHED
tcp        0      0 170.44.26.7:22              161.231.133.178:33938       ESTABLISHED
tcp        0      0 170.44.26.7:22              161.231.133.178:13875       ESTABLISHED
tcp        0      0 170.44.26.7:22              161.231.133.178:34968       ESTABLISHED
tcp        0      0 170.44.26.7:22              161.231.133.178:44212       ESTABLISHED
tcp        0      0 170.44.26.7:22              161.231.133.178:34967       ESTABLISHED

这里我们有一个监听套接字,以及由该套接字上的accept() 产生的几个连接(每个连接都由自己的套接字支持)。

【讨论】:

以上是关于accept() 函数是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

accept函数的用法

谁能告诉我accept()函数返回一个新的套接字,所谓新套接字怎么理解?

调用 fork() 后 SSL_accept 挂起

socket 编程中 accept 函数返回

200分,C++网络通信,高手,工作过的进!!

accept函数