You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Tkinter GUI聊天室点击connect触发WinError10038错误如何解决

报错根因

  1. 你在客户端代码初始化阶段就直接启动了receive和write两个后台线程,此时用户还没点击connect按钮建立连接,线程内调用client.recv()会直接触发异常,执行异常分支里的client.close()把套接字关闭。等你点击connect按钮调用client.connect()时,操作的已经是被关闭的无效套接字,就会抛出10038错误。
  2. 另外你当前的昵称获取逻辑是窗口刚启动就执行nickname = entry3.get(),此时用户还没输入昵称,拿到的永远是空字符串,不符合业务逻辑。

修复方案

调整逻辑顺序:

  • 套接字初始化、接收/发送线程启动都挪到connect函数内,仅在用户点击连接、填写完所有参数后再执行
  • 昵称获取也放在connect函数内,等用户输入完成后再读取
  • 增加重复点击连接的防护逻辑
  • 增加连接异常捕获逻辑

修复后的完整客户端代码如下:

import socket
import threading
import tkinter as tk

root = tk.Tk()
canvas1 = tk.Canvas(root, width=600, height=600)
canvas1.pack()

# IP输入框
entry1 = tk.Entry(root) 
canvas1.create_window(200, 140, window=entry1)
# 端口输入框
entry2 = tk.Entry(root) 
canvas1.create_window(200, 240, window=entry2)
# 昵称输入框
entry3 = tk.Entry(root) 
canvas1.create_window(200, 340, window=entry3)

client = None
connected = False
nickname = ""

def connect():
    global client, connected, nickname, receive_thread, write_thread
    if connected:
        return
    # 读取用户输入的参数
    ip = entry1.get()
    port = entry2.get()
    nickname = entry3.get()
    if not ip or not port or not nickname:
        print("请填写完整的IP、端口和昵称")
        return
    try:
        # 初始化套接字并发起连接
        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client.connect((ip, int(port)))
        connected = True
        print("连接成功")
        # 连接成功后再启动收、发线程
        receive_thread = threading.Thread(target=receive, daemon=True)
        receive_thread.start()
        write_thread = threading.Thread(target=write, daemon=True)
        write_thread.start()
    except Exception as e:
        print(f"连接失败:{e}")
        if client:
            client.close()
        connected = False

button1 = tk.Button(text='connect', command=connect)
canvas1.create_window(200, 180, window=button1)

def receive():
    global connected
    while connected:
        try:
            message = client.recv(1024).decode('ascii')
            if message == 'NICK':
                client.send(nickname.encode('ascii'))
            else:
                print(message)
        except:
            print("连接断开")
            break
    connected = False
    client.close()

def write():
    global connected
    while connected:
        try:
            content = input("")
            message = f'{nickname}: {content}'
            client.send(message.encode('ascii'))
        except:
            print("连接断开")
            break
    connected = False
    client.close()

root.mainloop()

注:代码中给线程加了daemon=True参数,保证关闭窗口时后台线程会同步退出,不会残留进程。

内容的提问来源于stack exchange,提问作者Elias Havas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 21:12:03