Python 实现 TCP 服务器与客户端通信:从 Python 2 到 Python 3 的完整指南
本文详细介绍如何使用 Python 的 socket 模块创建 TCP 服务器和客户端。通过时间戳回显服务器的实例,演示了从绑定端口、监听连接到收发数据的完整流程。重点解析了 Python 2 与 Python 3 在字符串与字节处理上的差异,提供了兼容两个版本的代码实现,帮助开发者掌握网络编程基础。
TCP 通信的基本原理与流程
在 Python 中进行网络编程,核心在于使用 socket 模块。TCP(传输控制协议)是一种面向连接的通信协议,其通信过程通常分为服务器端和客户端两个部分。服务器端负责监听特定端口,等待客户端的连接请求;客户端则主动发起连接,建立通信通道后交换数据。
一个典型的 TCP 交互流程包含以下关键步骤:
- 服务器端初始化:创建套接字,绑定 IP 地址和端口号,并设置监听队列。
- 等待连接:服务器进入阻塞状态,等待客户端的连接请求(
accept)。 - 建立连接:客户端发起连接(
connect),双方建立 TCP 连接。 - 数据收发:通过套接字发送和接收数据。服务器接收数据后,通常会附加时间戳并回传给客户端。
- 断开连接:通信结束后,双方关闭套接字以释放资源。
Python 2 环境下的实现
在 Python 2.7 环境中,字符串与字节数组的处理相对宽松,可以直接进行拼接和发送。以下代码展示了如何在 Python 2 中实现一个时间戳 TCP 服务器和客户端。
服务器端代码
#coding:utf-8
from socket import *
from time import ctime
print("=====================时间戳TCP服务器=====================");
HOST = '' #主机号为空白表示可以使用任何可用的地址。
PORT = 21567 #端口号
BUFSIZ = 1024 #接收数据缓冲大小
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM) #创建TCP服务器套接字
tcpSerSock.bind(ADDR) #套接字与地址绑定
tcpSerSock.listen(5) #监听连接,同时连接请求的最大数目
while True:
print('等待客户端的连接...')
tcpCliSock, addr = tcpSerSock.accept() #接收客户端连接请求
print('取得连接:', addr)
while True:
data = tcpCliSock.recv(BUFSIZ) #连续接收指定字节的数据,接收到的是字节数组
if not data: #如果数据空白,则表示客户端退出,所以退出接收
break
tcpCliSock.send('[%s] %s' % (ctime(), data)) #向客户端发送时间戳数据
tcpCliSock.close() #关闭与客户端的连接
tcpSerSock.close() #关闭服务器socket服务器端代码首先创建了一个 TCP 套接字,并将其绑定到空主机地址(即所有可用地址)和指定端口 21567。通过 listen(5) 设置监听队列长度为 5。在无限循环中,服务器调用 accept() 阻塞等待客户端连接。一旦连接建立,服务器进入另一个循环,接收客户端发送的数据。如果接收到的数据为空(表示客户端断开),则跳出循环并关闭该客户端的套接字。服务器将接收到的数据与当前时间戳拼接后发送回客户端。
客户端代码
#coding:utf-8
from socket import *
print("=====================TCP客户端=====================");
HOST = '127.0.0.1' #服务器ip地址,等价于localhost
PORT = 21567 #通信端口号
BUFSIZ = 1024 #接收数据缓冲大小
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM) #创建客户端套接字
tcpCliSock.connect(ADDR) #发起TCP连接
while True:
data = raw_input('> ') #接收用户输入
if not data: #如果用户输入为空,直接回车就会发送"",""就是代表false
break
tcpCliSock.send(data) #客户端发送消息
data = tcpCliSock.recv(BUFSIZ) #接收回应消息,接收到的是字节数组
if not data: #如果接收服务器信息失败,或没有消息回应
break
print(data) #打印回应消息
tcpCliSock.close() #关闭客户端socket客户端代码连接到本地回环地址 127.0.0.1 的 21567 端口。使用 raw_input() 获取用户输入,并通过 send() 方法将数据发送给服务器。随后,客户端调用 recv() 接收服务器的响应(包含时间戳),并将其打印出来。如果服务器断开连接,recv() 将返回空字节,客户端随之退出循环并关闭连接。
Python 3 环境下的适配与差异
在 Python 3 中,字符串(str)与字节数组(bytes)的区别变得严格。socket 通信要求发送和接收的数据必须是字节数组。因此,在 Python 3 中实现时,需要进行显式的编码和解码操作。
服务器端适配
#coding:utf-8
from socket import *
from time import ctime
print("=====================时间戳TCP服务器=====================");
HOST = '127.0.0.1' #主机号为空白表示可以使用任何可用的地址。
PORT = 21567 #端口号
BUFSIZ = 1024 #接收数据缓冲大小
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM) #创建TCP服务器套接字
tcpSerSock.bind(ADDR) #套接字与地址绑定
tcpSerSock.listen(5) #监听连接,同时连接请求的最大数目
while True:
print('等待客户端的连接...')
tcpCliSock, addr = tcpSerSock.accept() #接收客户端连接请求
print('取得连接:', addr)
while True:
data = tcpCliSock.recv(BUFSIZ) #连续接收指定字节的数据,接收到的是字节数组
if not data: #如果数据空白,则表示客户端退出,所以退出接收
break
#tcpCliSock.send('[%s] %s' % (bytes(ctime(), 'utf-8'), data))
tcpCliSock.send(bytes('[%s] %s' % (ctime(), data.decode('utf-8')), 'utf-8')) #向客户端发送时间戳数据,必须发送字节数组
tcpCliSock.close() #关闭与客户端的连接
tcpSerSock.close() #关闭服务器socket在 Python 3 的服务器端,关键变化在于 send() 方法。由于 ctime() 返回的是字符串,而 data 是字节数组,直接拼接会导致类型错误。因此,代码中先将 data 解码为字符串(data.decode('utf-8')),与时间戳拼接成完整字符串,再使用 bytes(..., 'utf-8') 将其编码为字节数组后发送。
客户端端适配
#coding:utf-8
from socket import *
print("=====================TCP客户端=====================");
HOST = '127.0.0.1' #服务器ip地址,等价于localhost
PORT = 21567 #通信端口号
BUFSIZ = 1024 #接收数据缓冲大小
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM) #创建客户端套接字
tcpCliSock.connect(ADDR) #发起TCP连接
while True:
data = input('> ') #接收用户输入
if not data: #如果用户输入为空,直接回车就会发送"",""就是代表false
break
tcpCliSock.send(bytes(data, 'utf-8')) #客户端发送消息,必须发送字节数组
data = tcpCliSock.recv(BUFSIZ) #接收回应消息,接收到的是字节数组
if not data: #如果接收服务器信息失败,或没有消息回应
break
print(data.decode('utf-8')) #打印回应消息,或者str(data,"utf-8")
tcpCliSock.close() #关闭客户端socket客户端端的适配同样涉及编码和解码。用户输入通过 input() 获取(Python 3 中 raw_input 已更名为 input),发送前使用 bytes(data, 'utf-8') 编码为字节数组。接收到的响应数据也是字节数组,因此打印前需要调用 decode('utf-8') 将其转换为字符串,以便正确显示。
运行步骤与注意事项
要成功运行上述程序,请遵循以下步骤:
- 启动服务器:首先运行服务器端代码。服务器将监听指定端口,直到有客户端连接。
- 启动客户端:在另一个终端或命令行窗口中运行客户端代码。客户端将尝试连接到服务器的 IP 和端口。
- 交互测试:在客户端输入文本并回车,服务器将接收数据,附加当前时间戳,并将结果发送回客户端。客户端将显示包含时间戳的响应信息。
- 结束通信:在客户端直接回车(不输入任何内容),程序将检测到空数据并退出循环,关闭连接。服务器端也会检测到客户端断开,关闭该客户端的套接字,并继续等待下一个连接。
需要注意的是,服务器端的 HOST 设置为空字符串时,表示监听所有可用的网络接口。如果指定为 '127.0.0.1',则仅监听本地回环地址。在实际部署中,应根据安全需求选择合适的绑定地址。
以上就是 Python 使用 socket 创建 TCP 服务器和客户端的详细内容,更多关于 Python 网络编程的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













