通用编程:在服务器套接字的accept()方法中,到底发生了什么。在低层,服务器套接字和客户端套接字有什么不同?
发布于 2009-04-21 21:03:17
首先,服务器套接字通常绑定到众所周知的名称(在本例中为端口),并且它们使用listen()建立自己。这才是真正不同之处所在,因为客户端套接字使用connect()建立自己。在套接字上调用listen()会导致内核的tcp/ip实现开始接受发送到套接字的绑定名称(端口)的连接。无论您是否调用过accept(),都会发生这种情况。
accept()只是为您的服务器提供了一种访问连接到侦听套接字的客户端套接字并与之交互的方法。
发布于 2009-04-25 07:06:11
在较低的级别上,套接字就是套接字,无论它们是在服务器应用程序中还是在客户端应用程序中使用。两者之间的区别在于每种应用程序进行的系统调用。
服务器套接字将调用bind()以与端口关联。它们希望与某个端口相关联,以便其他程序知道从何处访问它们。客户端套接字可以调用bind(),但几乎不会这样做,因为这没有太多意义。如果套接字不调用bind(),操作系统将只为它选择一个临时端口,这对于客户端来说是很好的,因为它们正在进行调用;没有人需要调用它们。
服务器套接字调用listen()。这在其他答案中解释得很好。
服务器套接字调用accept(),我认为这是您问题的症结所在,因为它一开始有点神秘。需要掌握的重要一点是,在调用accept()时,内核将传回一个新的套接字。它现在独立于原始侦听套接字,并且是您的服务器将用于与其对等方进行通信的套接字。
理解侦听套接字如何在接受的连接执行其操作时继续侦听的关键是理解tcp连接依赖于(1)本地地址(2)本地端口(3)外部地址(4)外部端口的4元组。这些定义了一个唯一的连接。在accept()回传新套接字之前,内核使用这些值来创建各种结构,以便在与tcp/ip堆栈协作时,具有此元组的所有流量都将转到连接的套接字。即使您的服务器可能有一千个本地地址为192.168.1.100端口80的连接,但客户端的地址和端口组合将始终不同,因此元组始终是唯一的。
发布于 2009-04-21 21:26:56
如果你真的感兴趣,那么我建议你阅读TCP/IP Illustrated, Volume 2。如果你想要一个不那么“直截了当”的答案,那么:
socket()系统调用中指定的协议和bind()系统调用中指定的寻址信息构成。listen()系统调用时,网络堆栈将创建一个队列,将挂起的连接放入队列中。队列大小的提示作为listen().backlog参数给出,然后调用accept()从connect()套接字中拉出新连接通过在对send()的调用中指定服务器端点,然后使用connect()或发送数据,将消息发送到服务器套接字。客户端调用connect()时,连接被推送到服务器端队列,直到服务器接受该连接。
然而,此描述仅对TCP/IP套接字有效。由于UDP套接字不是(必须)连接的,因此UDP的情况更简单且有很大的不同。
https://stackoverflow.com/questions/774571
复制相似问题