socket 中listen() 与accept() 的一些理解

Socket通信流程解析
本文详细解释了服务器端如何使用socket()创建监听套接字、通过listen()监听客户端连接请求及accept()接受连接并创建新的套接字进行通信的过程。同时介绍了如何关闭不再使用的套接字。

在服务器端,socket()返回的套接字用于监听(listen)和接受(accept)客户端的连接请求。这个套接字不能用于与客户端之间发送和接收数据。

 

accept()接受一个客户端的连接请求,并返回一个新的套接字。所谓“新的”就是说这个套接字与socket()返回的用于监听和接受客户端的连接请求的套接字不是同一个套接字。与本次接受的客户端的通信是通过在这个新的套接字上发送和接收数据来完成的。

 

再次调用accept()可以接受下一个客户端的连接请求,并再次返回一个新的套接字(与socket()返回的套接字、之前accept()返回的套接字都不同的新的套接字)。这个新的套接字用于与这次接受的客户端之间的通信。

 

假设一共有3个客户端连接到服务器端。那么在服务器端就一共有4个套接字:第1个是socket()返回的、用于监听的套接字;其余3个是分别调用3次accept()返回的不同的套接字。

 

如果已经有客户端连接到服务器端,不再需要监听和接受更多的客户端连接的时候,可以关闭由socket()返回的套接字,而不会影响与客户端之间的通信。

 

当某个客户端断开连接、或者是与某个客户端的通信完成之后,服务器端需要关闭用于与该客户端通信的套接字。

 

举个简单的例子(以下代码只是示范性的,用于说明不同套接字的作用,实际的函数会需要更多的参数):

/* 建立用于监听和接受客户端连接请求的套接字 */
server_sock = socket();
/* 绑定监听的IP地址和端口 */
bind(server_sock);
/* 开始监听 */
listen(server_sock);
/**
* 等待客户端连接请求,在没有客户端连接请求到来之前,
* 程序会一直阻塞在这个函数里。
*/
client_sock = accept(server_sock);
/**
* 已经接受客户端连接请求,accept()函数创建并返回了一个
* 新的套接字client_sock,用于与客户端通信。
* 如果不再需要接受其他客户端的连接请求,可以关闭监听
* 套接字了。
*/
close(server_sock);
/* 发送数据到客户端 */
send(client_sock, data);
/* 从客户端接收数据 */
recv(client_sock, data);
/* 通信结束,关闭与客户端通信的套接字 */
close(client_sock);
在Python的socket编程中,`listen`和`accept`函数是服务器端套接字编程的重要组成部分。 ### `listen`函数 `listen`函数用于将一个套接字转换为监听套接字,使其能够接受客户端的连接请求。在调用`socket()`函数创建套接字后,该套接字默认处于主动模式,即用于发起连接。而`listen`函数将其转换为被动模式,用于监听客户端的连接。 `listen`函数的原型为:`socket.listen(backlog)`,其中`backlog`是一个整数,表示允许的最大连接请求队列长度。当有多个客户端同时发起连接请求时,如果当前已经有`backlog`个连接请求在队列中等待处理,新的连接请求将被拒绝。 下面是一个简单的示例代码: ```python import socket # 创建一个TCP/IP套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定地址和端口 server_address = ('localhost', 8888) server_socket.bind(server_address) # 开始监听,允许最多5个连接请求排队等待处理 server_socket.listen(5) ``` ### `accept`函数 `accept`函数用于接受一个客户端的连接请求,并返回一个新的套接字对象和客户端的地址信息。在服务器端,`socket()`返回的套接字用于监听(`listen`)和接受(`accept`),这个套接字不能用于客户端之间发送和接收数据。`accept`函数接受一个客户端的连接请求,并返回一个新的套接字,不同于`socket()`返回的用于监听和接受客户端连接请求的套接字;此客户端通信是通过这个新的套接字上发送和接收数据来完成的 [^1]。 `accept`函数的原型为:`conn, addr = socket.accept()`,其中`conn`是新的套接字对象,用于客户端进行通信;`addr`是客户端的地址信息,通常是一个包含IP地址和端口号的元组。 以下是结合`listen`和`accept`函数的完整示例代码: ```python import socket # 创建一个TCP/IP套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定地址和端口 server_address = ('localhost', 8888) server_socket.bind(server_address) # 开始监听,允许最多5个连接请求排队等待处理 server_socket.listen(5) print('等待客户端连接...') # 接受客户端连接 conn, addr = server_socket.accept() print(f'连接来自: {addr}') # 接收客户端发送的数据 data = conn.recv(1024) print(f'收到数据: {data.decode()}') # 关闭连接 conn.close() server_socket.close() ``` ### 原理概述 - **`listen`函数原理**:当调用`listen`函数时,操作系统会为该套接字创建一个连接请求队列,用于存储客户端的连接请求。`backlog`参数指定了这个队列的最大长度。当有客户端发起连接请求时,请求会被放入队列中等待处理。 - **`accept`函数原理**:`accept`函数会从连接请求队列中取出一个连接请求,并创建一个新的套接字对象。这个新的套接字对象客户端建立了一对一的连接,用于后续的数据传输。同时,`accept`函数会返回客户端的地址信息,方便服务器识别客户端。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值