如何通过网络实现Python脚本间通信?含跨版本Socket重连问题
问题分析与解决方案
核心问题
你的服务端当前仅处理一次客户端连接,处理完成后就退出了,没有回到监听状态等待新连接;同时客户端的连接逻辑是自动发送10次数据后关闭,不符合“手动断开”的需求,且按钮变量名存在错误导致GUI功能异常。
服务端修改(Python3)
将服务端改为循环监听模式,处理完一个客户端连接后自动回到监听状态,同时持续向客户端发送数据直到对方断开:
import socket import time HOST = "127.0.0.1" PORT = 65432 # 创建并绑定socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((HOST, PORT)) s.listen() print(f"服务端已启动,监听 {HOST}:{PORT}") while True: # 等待新连接 conn, addr = s.accept() print(f"已连接客户端: {addr}") try: # 持续向客户端发送数据,直到客户端断开 count = 0 while True: send_data = f"服务端发送数据: {count}".encode('utf-8') conn.sendall(send_data) print(f"已发送: {send_data.decode('utf-8')}") count += 1 time.sleep(1) # 尝试接收客户端数据(检测是否断开) conn.settimeout(0.5) try: data = conn.recv(1024) if not data: break print(f"收到客户端回复: {data.decode('utf-8')}") except socket.timeout: continue except ConnectionResetError: print(f"客户端 {addr} 强制断开连接") finally: conn.close() print(f"与客户端 {addr} 的连接已关闭,等待新连接...")
修改说明
- 外层
while True循环:让服务端处理完一个连接后,重新调用s.accept()等待新连接 - 内部发送循环:持续向客户端发送数据,通过
recv超时检测客户端是否断开 - 异常处理:捕获
ConnectionResetError处理客户端强制断开的情况
客户端修改(Python2.7)
修正GUI变量错误,实现“手动连接/断开”功能,用后台线程处理socket通信避免卡住GUI:
import Tkinter as tk import socket import random import time import threading keyState = False HOST = '127.0.0.1' PORT = 65432 client_socket = None # 全局保存socket实例 stop_flag = False # 控制发送线程的停止信号 def onButton(): global keyState if not keyState: keyState = True softkey_button.config(relief='sunken') # 启动连接线程,避免阻塞GUI threading.Thread(target=connectSocket, daemon=True).start() print(keyState) else: keyState = False softkey_button.config(relief='raised') disconnectSocket() print(keyState) def connectSocket(): global client_socket, stop_flag print("connectSocket()") stop_flag = False try: client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect((HOST, PORT)) print("已连接到服务端") # 持续接收服务端数据,直到断开 while not stop_flag: try: data = client_socket.recv(1024) if not data: print("服务端已断开连接") break print 'Received', repr(data) except socket.error: break except Exception as e: print(f"连接失败: {str(e)}") keyState = False softkey_button.config(relief='raised') finally: if client_socket: client_socket.close() def disconnectSocket(): global client_socket, stop_flag print("disconnectSocket()") stop_flag = True if client_socket: try: client_socket.close() print("已断开与服务端的连接") except: pass #Main GUI root = tk.Tk() root.title('Python Socket Test') root.configure(background='white') root.geometry("200x300") #Button softkey_button = tk.Button(root, text="Softkey", command=onButton, relief='flat') softkey_button.place(x=75,y=200) root.mainloop()
修改说明
- 全局变量
client_socket:保存socket实例,方便断开时关闭 - 后台线程处理连接:避免socket通信阻塞Tkinter GUI主线程
stop_flag:控制接收线程的停止,实现手动断开功能- 修正按钮变量名:将错误的
key_button改为实际的softkey_button - 完善断开逻辑:在
disconnectSocket中主动关闭socket并停止接收线程
测试步骤
- 先启动服务端,会显示“服务端已启动,监听...”
- 启动客户端,点击按钮连接,会收到服务端持续发送的数据
- 再次点击按钮断开连接,服务端会显示连接关闭并等待新连接
- 可以多次点击客户端按钮实现连接/断开,服务端都会正常处理
内容的提问来源于stack exchange,提问作者JNDStackOverflow
相关产品推荐
相关产品推荐

