凌峰创科服务平台

TCP服务器socket对象如何创建与管理?

服务器 Socket 是什么?

在 TCP 编程中,服务器端的 Socket 对象(在 Python 中通常称为 socket.socket 对象,但特指处于“监听”状态的那个)扮演着一个“门卫”或“前台接待员”的角色。

TCP服务器socket对象如何创建与管理?-图1
(图片来源网络,侵删)

它的主要职责是:

  1. 绑定:告诉操作系统这个应用程序将在哪个网络地址(IP 地址和端口号)上等待客户端的连接请求。
  2. 监听:进入一种“待命”状态,时刻检查是否有客户端尝试连接。
  3. 接受:当有客户端连接时,它会“接受”这个连接,并为这个新的客户端连接创建一个新的、专门的 Socket 对象,用于后续的数据通信。

一个非常重要的区分: 一个 TCP 服务器通常管理着 两种 Socket 对象:

  1. 监听 Socket:这是服务器启动时创建的那个“门卫”,它本身不负责数据传输,只负责等待并接受新的连接,一个服务器通常只有一个监听 Socket。
  2. 客户端连接 Socket:每当“门卫”接受一个新客户端后,就会创建一个新的 Socket 对象,这个新的 Socket 专门用于与那个特定的客户端进行一对一的数据收发,服务器可以同时为多个客户端服务,因此会有多个这样的客户端连接 Socket。

服务器端 Socket 的生命周期与关键方法

下面我们通过一个典型的 TCP 服务器工作流程,来理解服务器 Socket 对象是如何被创建和使用的,我们以 Python 的 socket 模块为例,因为它非常直观。

第 1 步:创建 Socket 对象

这是所有操作的开始,我们需要调用 socket.socket() 来创建一个 Socket 对象。

TCP服务器socket对象如何创建与管理?-图2
(图片来源网络,侵删)
import socket
# 创建一个 TCP (SOCK_STREAM) 的 Socket 对象
# 使用 IPv4 地址 (AF_INET)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  • socket.AF_INET: 指定使用 IPv4 地址族,如果使用 IPv6,则是 socket.AF_INET6
  • socket.SOCK_STREAM: 指定使用 TCP 协议,如果是 UDP,则是 socket.SOCK_DGRAM

server_socket 就是一个普通的、未绑定的 Socket 对象,就像一张空白的“电话机”。

第 2 步:绑定 地址和端口

“门卫”需要知道自己的“办公室”在哪里。bind() 方法就是用来设置这个地址和端口的。

# 定义服务器的地址和端口
# '0.0.0.0' 表示监听本机所有可用的网络接口
HOST = '0.0.0.0'
PORT = 65432  # 选择一个大于 1023 的端口号
# 将 Socket 绑定到指定的地址和端口
server_socket.bind((HOST, PORT))
print(f"服务器已绑定到 {HOST}:{PORT}")
  • 地址'127.0.0.1' 是本地回环地址,只有本机可以访问。'0.0.0.0' 表示监听本机所有网络接口(包括 Wi-Fi、以太网等),允许同一网络下的其他计算机访问。
  • 端口:端口号是一个 16 位的整数,范围是 0-65535,0-1023 是系统保留端口(如 HTTP 的 80,HTTPS 的 443),普通应用程序应该使用 1024 以上的端口号。

注意:如果端口已被占用,bind() 会抛出 OSError 异常。

第 3 步:开始监听

“门卫”可以开始站岗了。listen() 方法让 Socket 进入监听状态,等待客户端的连接请求。

TCP服务器socket对象如何创建与管理?-图3
(图片来源网络,侵删)
# 开始监听,允许最多 5 个客户端在队列中等待连接
# backlog 参数表示等待队列的最大长度
server_socket.listen(5)
print("服务器正在监听...")
  • backlog 参数:这非常重要,它指定了当服务器正在处理一个连接时,可以有多少个新的连接请求在队列中等待,如果队列满了,新的客户端连接请求可能会被拒绝(客户端会收到一个 ECONNREFUSED 错误),设置为 5 是一个常见的做法,可以根据服务器的负载能力进行调整。

第 4 步:接受连接

这是最核心的一步。accept() 方法会“阻塞”程序的执行,直到有一个客户端成功连接到服务器,一旦有客户端连接,accept() 就会返回两个值:

  1. 一个新的 Socket 对象:这个对象专门用于与刚刚连接的客户端进行通信,我们称之为 client_socket
  2. 客户端的地址:一个包含 (ip_address, port) 的元组,告诉你是哪个客户端连上来了。
# accept() 是一个阻塞方法,会一直等待直到有客户端连接
# client_socket 是一个新的 Socket,用于和这个客户端通信
# client_address 是客户端的地址
client_socket, client_address = server_socket.accept()
print(f"已接受来自 {client_address} 的连接!")

你拥有了两个 Socket:

  • server_socket:仍在监听,等待下一个客户端连接。
  • client_socket:正在与第一个客户端进行通信。

第 5 步:与客户端通信

使用 client_socket 这个新对象,我们可以通过 send()recv() 方法与客户端收发数据。

# 接收客户端发来的数据
# recv() 也是一个阻塞方法,会等待数据到来
data = client_socket.recv(1024)  # 最多接收 1024 字节
print(f"收到来自 {client_address} 的数据: {data.decode('utf-8')}")
# 向客户端发送数据
response = "你好,客户端!"
client_socket.sendall(response.encode('utf-8'))
print(f"已向 {client_address} 发送响应: {response}")

第 6 步:关闭连接

当与一个客户端的通信结束后,需要关闭对应的 client_socket,以释放系统资源。

# 关闭与客户端的连接
client_socket.close()
print(f"与 {client_address} 的连接已关闭。")

第 7 步:关闭服务器(可选)

如果服务器程序要退出,就需要关闭最初的监听 server_socket

# 关闭服务器监听套接字
server_socket.close()
print("服务器已关闭。")

完整的简单示例代码

下面是一个完整的、可以运行的 TCP 服务器和客户端示例。

服务器代码 (server.py)

import socket
HOST = '0.0.0.0'  # 监听所有可用的网络接口
PORT = 65432      # 监听端口
# 1. 创建 socket 对象
# AF_INET -> IPv4, SOCK_STREAM -> TCP
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
    # 2. 绑定地址和端口
    server_socket.bind((HOST, PORT))
    # 3. 开始监听
    server_socket.listen()
    print(f"服务器正在监听 {HOST}:{PORT}...")
    # 4. 接受客户端连接 (这是一个阻塞调用)
    # conn 是一个新的 socket 对象,用于与客户端通信
    # addr 是客户端的地址
    conn, addr = server_socket.accept()
    with conn:
        print(f"已连接到 {addr}")
        while True:
            # 5. 接收客户端数据
            data = conn.recv(1024)
            if not data:
                # recv() 返回空数据,说明客户端已关闭连接
                break
            print(f"收到来自 {addr} 的消息: {data.decode('utf-8')}")
            # 6. 发送响应给客户端
            response = f"服务器已收到你的消息: {data.decode('utf-8')}"
            conn.sendall(response.encode('utf-8'))
        print(f"与 {addr} 的连接已关闭。")

客户端代码 (client.py)

import socket
HOST = '127.0.0.1'  # 服务器的 IP 地址 (本地回环)
PORT = 65432        # 服务器的端口
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # 连接到服务器
    s.connect((HOST, PORT))
    print(f"已连接到服务器 {HOST}:{PORT}")
    # 发送消息给服务器
    message = "你好,服务器!"
    s.sendall(message.encode('utf-8'))
    print(f"已发送消息: {message}")
    # 接收服务器的响应
    data = s.recv(1024)
    print(f"收到服务器的响应: {data.decode('utf-8')}")
特性 描述
角色 服务器的“门卫”,负责等待和接受客户端连接。
创建 通过 socket.socket(socket.AF_INET, socket.SOCK_STREAM) 创建。
核心方法 bind(), listen(),
分享:
扫描分享到社交APP
上一篇
下一篇