likes
comments
collection
share

Python Socket编程:从基础到多线程“Socket” 这个词直接翻译为“插座”,可以理解为在服务的两端各自安装

作者站长头像
站长
· 阅读数 48

引言

什么是 Socket

在物理世界中,数据传输通常依赖电缆或光纤,而在应用层,服务则基于 TCP/IP 协议进行数据传输。直接使用代码操作 TCP/IP 在不同计算机之间建立连接并进行数据传输和交换,除了需要专业知识外,还需考虑许多细节,这可能会变得相当繁琐。因此,Socket(套接字)应运而生。

Socket 是计算机网络编程中的一种抽象概念,最早由 BSD 开发的一套通用网络接口,用于在网络上进行通信。通过使用 Socket,网络开发的难度大大降低。

Socket 的工作原理

Socket 通信涉及几个关键步骤:服务器监听、客户端请求和连接确认。服务器通过调用 socket()bind()listen() 函数来初始化并监听端口,而客户端则通过 connect() 函数向服务器发起连接请求。当服务器接收到连接请求后,使用 accept() 函数接受连接,从而建立通信。

“Socket” 这个词直接翻译为“插座”,可以理解为在服务的两端各自安装了一个插座,而 TCP/IP 协议则是连接这两个插座的电线。

第一部分:基础Socket服务

创建Socket服务

首先,我们将创建一个基础的socket服务。这个服务将监听特定端口,等待客户端连接,并接收客户端发送的消息。

import socket  # 导入socket模块

def main():
    host = '127.0.0.1'  # 服务器的IP地址
    port = 12345  # 服务器的端口号

    # 创建socket对象,AF_INET表示使用IPv4地址,SOCK_STREAM表示使用TCP协议
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 绑定地址和端口
    server_socket.bind((host, port))
    
    # 开始监听
    server_socket.listen()
    print(f"Listening on {host}:{port}")  # 打印服务器监听的地址和端口

    while True:
        # 接受客户端连接,返回一个新的socket对象和客户端地址
        client_socket, addr = server_socket.accept()
        print(f"Accepted connection from {addr}")  # 打印客户端地址
        
        # 接收客户端发送的消息,1024表示接收的最大字节数
        message = client_socket.recv(1024).decode('utf-8')
        print(f"Received message: {message}")  # 打印接收到的消息
        
        # 将接收到的消息发送回客户端
        client_socket.sendall(message.encode('utf-8'))
        
        # 关闭客户端socket
        client_socket.close()

if __name__ == "__main__":
    main()

使用nc命令测试

使用nc命令可以测试我们的socket服务。在命令行中输入以下命令:

nc 127.0.0.1 12345

然后输入一些文本并回车,你将看到服务器回显相同的文本。

问题:阻塞和不支持多客户端

上述代码虽然可以工作,但它存在一个问题:服务器在处理一个客户端时会阻塞,无法同时处理多个客户端。这意味着如果上一个客户端连接后没有断开,其他客户端将无法连接。

第二部分:使用多线程

为了解决这个问题,我们可以引入多线程。每当有新的客户端连接时,我们创建一个新的线程来处理这个客户端。

多线程Socket服务

import socket
import threading  # 导入线程模块

# 定义处理客户端的函数
def handle_client(client_socket, addr):
    print(f"Accepted connection from {addr}")  # 打印客户端地址
    while True:
        # 接收客户端发送的消息
        message = client_socket.recv(1024).decode('utf-8')
        if not message:  # 如果没有接收到消息,则退出循环
            break
        print(f"Received message: {message}")  # 打印接收到的消息
        # 将接收到的消息发送回客户端
        client_socket.sendall(message.encode('utf-8'))
    # 关闭客户端socket
    client_socket.close()

def main():
    host = '127.0.0.1'  # 服务器的IP地址
    port = 12345  # 服务器的端口号

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind((host, port))
    # 开始监听,参数5表示最多可以有5个连接等待接受
    server_socket.listen(5)
    print(f"Listening on {host}:{port}")  # 打印服务器监听的地址和端口

    while True:
        # 接受客户端连接
        client_socket, addr = server_socket.accept()
        print(f"Connection from {addr} has been established.")  # 打印客户端地址
        
        # 创建一个线程来处理客户端
        client_handler = threading.Thread(
            target=handle_client,  # 指定线程要执行的函数
            args=(client_socket, addr)  # 传递给函数的参数
        )
        # 启动线程
        client_handler.start()

if __name__ == "__main__":
    main()

使用nc命令测试多线程服务

再次使用nc命令测试,你会发现现在可以同时处理多个客户端连接了。

总结

本文介绍了 Socket 的一些基本概念、发展历程以及工作原理,并通过 Python 实现了一个基础的 Socket 服务,紧接着介绍了如何使用多线程来允许多个客户端同时连接。希望能对大家有所帮助!

以上。

转载自:https://juejin.cn/post/7418797990306332735
评论
请登录