Python Socket编程:从基础到多线程“Socket” 这个词直接翻译为“插座”,可以理解为在服务的两端各自安装
引言
什么是 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