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

Python Socket报错OSError: [WinError 10038] 问题求助

Kivy+Socket聊天App发送消息报错WinError 10038的解决方案

问题描述

使用Kivy和Socket开发可在PC与Android运行的聊天App,输入用户名连接服务器后尝试发送消息,触发如下错误:

File "c:\Users\adebu\Documents\Andriod chat app\webchat.kv", line 82, in <module>
    on_press: root.send_message()
File "c:\Users\adebu\Documents\Andriod chat app\main.py", line 20, in send_message
    client.send(cmessage.encode("utf-8"))
OSError: [WinError 10038] An operation was attempted on something that is not a socket"

相关代码如下:

客户端代码

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

import socket
import threading

kivy.require("1.9.0")

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

class MyRoot(BoxLayout):

    
    def __int__(self):
        super(MyRoot, self).__init__()

    def send_message(self):      
        cmessage = (f"{self.nickname_text.text}: {self.message_text.text}")
        client.send(cmessage.encode("utf-8"))
    
        
    def connect_to_server(self):
        if self.nickname_text != "":
            client.connect((self.ip_text.text, 9999))
            message = client.recv(1024).decode('utf-8')
            if message == 'NICK':
                client.send(self.nickname_text.text.encode('utf-8'))
                self.send_btn.disable = True
                self.message_text.disable = True
                self.connect_btn.disable = True
                self.ip_text.disable = True

                self.make_invisible(self.connection_grid)
                self.make_invisible(self.connect_btn)

                thread = threading.Thread(target=self.receive)
                thread.start()

    def make_invisible(self, widget):
        widget.visible = False
        widget.size_hint_x = None
        widget.size_hint_y = None
        widget.height = 0
        widget.width = 0
        widget.txt = ""
        widget.opacity = 0

    def receive(self):
        stop = False
        while not stop:
            try:
                message = client.recv(1024).decode('utf-8')
                self.chat_text.text += message + "\n"
            except:
                print("ERROR")
                client.close()
                stop = True

class WebChat(App):

    def build(self):
        return MyRoot()

webChat = WebChat()
webChat.run()

Kivy布局文件

<MyRoot>

    ip_text: ip_text
    nickname_text: nickname_text
    connect_btn: connect_btn
    chat_text: chat_text
    message_text: message_text
    send_btn: send_btn
    connection_grid: connection_grid

    orientation: 'vertical'


    GridLayout:
        id: connection_grid
        rows: 1
        cols: 2
        padding: 10
        spacing: 10
        height: 125
        size_hint: (1, None)
        BoxLayout:
            orientation: 'vertical'
            Label:
                text: "Server IP"
                font_size: 42
                color: 180, 100, 50, 1
            TextInput:
                id: ip_text
                size_hint: (1, None)
                height: 50
                font_size: 36
        BoxLayout:
            orientation: 'vertical'
            Label:
                text: "Nickname"
                font_size: 42
                color: 180, 100, 50, 1
            TextInput:
                id: nickname_text
                size_hint: (1, None)
                height: 50
                font_size: 36
    Button:
        id:connect_btn
        text: "Connect"
        font_size: 32
        size: 100, 50
        size_hint: (1, None)
        height: 70
        on_press: root.connect_to_server()
        color: 180, 100, 50, 1
    Label:
        text: "Chat History"
        font_size: 42
        height: 50
        size_hint: (1, None)
        color: 23, 0, 0, 1
    TextInput:
        id: chat_text
        size_hint: (1, None)
        height: 450
        multiline: True
        font_size: 36
        readonly: True
        disabled: True
    Label:
        text: "Your Message"
        font_size: 42
        height: 50
        size_hint: (1, None)
        color: 23, 0, 0, 1
    TextInput:
        id: message_text
        font_size: 36
        disabled: True
    Button:
        id: send_btn
        text: "Send"
        font_size: 32
        size: 100, 50
        on_press: root.send_message()
        disabled: True

服务端代码

import socket
import threading
HOST = "localhost"
PORT = 9999

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))

server.listen()

clients = []
nicknames = []


def broadcast(message):
    for client in clients:
        client.send(message)


def handle_connection(client):
    stop = False
    while not stop:
        try:
            message = client.recv(1024)
            broadcast(message)
        except:
            index = client.index(client)
            client.remove(client)
            nickname = nicknames[index]
            nicknames.remove(nickname)
            broadcast(f"{nickname} left the chat!".encode('utf-8'))
            stop = True


def main():
    print("server is online...")
    while True:
        client, addr = server.accept()
        print(f"Connected to {addr}")
        
        client.send("NICK".encode('utf-8'))

        nickname = client.recv(1024).decode('utf-8')
        nicknames.append(nickname)
        clients.append(client)
        print(f"Nickname is {nickname}")

        broadcast(f"{nickname} joined the chat!".encode('utf-8'))

        client.send("You are now connected!".encode('utf-8'))

        thread = threading.Thread(target=handle_connection, args=(client,))
        thread.start()


if __name__ == '__main__':
    main()

错误原因及修复步骤

1. 客户端类构造函数拼写错误

MyRoot类的构造函数写成了__int__,正确应为__init__,这会导致Kivy控件初始化异常,间接影响套接字操作的正确性。

修复代码:

# 原代码
def __int__(self):
    super(MyRoot, self).__init__()

# 修改为
def __init__(self):
    super(MyRoot, self).__init__()

2. 连接成功后错误禁用发送控件

connect_to_server方法中,连接成功后错误设置了发送按钮和消息输入框为禁用状态,且Kivy中控件的禁用属性是disabled而非disable。

修复代码:

# 原代码
self.send_btn.disable = True
self.message_text.disable = True

# 修改为
self.send_btn.disabled = False
self.message_text.disabled = False

3. 服务端索引获取逻辑错误

handle_connection函数中,获取客户端索引时错误使用了client.index(client),正确应从clients列表中查找索引,同时移除客户端时也需操作clients列表。

修复代码:

# 原代码
index = client.index(client)
client.remove(client)

# 修改为
index = clients.index(client)
clients.remove(client)

4. 客户端昵称判断逻辑错误

connect_to_server方法中,判断昵称是否为空时直接比较控件对象而非其text属性,导致判断逻辑失效。

修复代码:

# 原代码
if self.nickname_text != "":

# 修改为
if self.nickname_text.text.strip():

5. Kivy控件属性错误

make_invisible方法中使用了不存在的visible和txt属性,Kivy控件无此类属性,需删除无效代码。

修复代码:

# 原代码
def make_invisible(self, widget):
    widget.visible = False
    widget.size_hint_x = None
    widget.size_hint_y = None
    widget.height = 0
    widget.width = 0
    widget.txt = ""
    widget.opacity = 0

# 修改为
def make_invisible(self, widget):
    widget.size_hint_x = None
    widget.size_hint_y = None
    widget.height = 0
    widget.width = 0
    widget.opacity = 0

验证修复

完成上述修改后,重启服务端和客户端,输入服务器IP和昵称连接,即可正常发送消息,不会再触发WinError 10038错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 05:42:26