套接字编程是网络通信的基础。无论是创建一个简单的聊天应用还是构建复杂的分布式系统,理解套接字的工作原理都是必不可少的。在本教程中,我们将探讨 Python 中的套接字编程,并通过示例代码展示如何使用套接字进行网络通信。
套接字的历史
套接字(Socket)最早由 BSD Unix 引入,是一种通过网络进行进程间通信(IPC)的机制。尽管套接字可以用于多种地址族(如 IPv4、IPv6、Unix 域套接字等),我们主要讨论 IPv4 地址族(INET),因为它覆盖了几乎 99% 的使用场景。
创建套接字
在 Python 中,创建一个套接字非常简单。我们使用 socket
模块来实现。具体步骤如下:
import socket
# 创建一个套接字对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
这里的 socket.AF_INET
指的是地址族(IPv4),socket.SOCK_STREAM
表示使用 TCP 协议。
使用套接字
通过套接字发送和接收数据是它的核心功能。这里我们展示如何发送和接收二进制数据。
发送数据:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 12345))
message = b'Hello, Server!'
client_socket.sendall(message)
接收数据:
connection, address = server_socket.accept()
data = connection.recv(1024)
print('Received:', data)
断开连接
当通信完成后,需要关闭套接字以释放资源。
client_socket.close()
connection.close()
server_socket.close()
非阻塞的套接字
默认情况下,套接字操作是阻塞的。这意味着在 recv()
函数完成之前,程序会一直等待数据。非阻塞套接字则允许程序在没有数据时继续执行其他操作。
可以使用 socket.setblocking(False) 将套接字设置为非阻塞模式,在这种模式下,sock.recv() 不会阻塞,而是立即返回。如果对方没有数据发送,则会返回一个空字节串。
server_socket.setblocking(False)
try:
connection, address = server_socket.accept()
except BlockingIOError:
# 没有连接请求时,继续执行其他操作
pass
完整示例代码
以下是一个完整的示例,展示了如何创建一个简单的 TCP 服务端和客户端,并进行数据传输。
服务端代码:
import socket
# 创建服务器套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(5)
print('等待连接...')
connection, address = server_socket.accept()
print('来自', address, '的连接')
data = connection.recv(1024)
print('接收到的数据:', data)
connection.close()
server_socket.close()
客户端代码:
import socket
# 创建客户端套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 12345))
message = b'Hello, Server!'
client_socket.sendall(message)
client_socket.close()
首先运行服务器端代码,然后运行客户端代码,你将在服务器端的终端看到打印出的 “Received: b’Hello, Server!'”,表明成功收到了客户端发送的消息。