【问题标题】:Getting an error in tkinter and message encoding在 tkinter 和消息编码中出现错误
【发布时间】:2021-10-21 22:44:28
【问题描述】:

我在一个 tcp 聊天室工作,当我运行它时,它显示昵称和谁加入,但消息没有通过,并且在第四次尝试发送消息后显示错误

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\f\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "besthost.py", line 59, in write
    self.sock.send(message.encode('utf-8'))
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

主机文件是


import socket
import threading
import tkinter
import tkinter.scrolledtext
from tkinter import simpledialog

HOST = '127.0.0.1'
PORT = 9091


class Client:

    def __init__(self, host, port):

        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect((host, port))

        msg = tkinter.Tk()
        msg.withdraw()

        self.nickname = simpledialog.askstring("nickname", "please choose a nickname", parent=msg)
        self.gui_done = False

        self.running = True
        gui_thread = threading.Thread(target=self.gui_loop)
        receive_thread = threading.Thread(target=self.receive)
        gui_thread.start()
        receive_thread.start()

    def gui_loop(self):
        self.win = tkinter.Tk()
        self.win.configure(bg="darkolivegreen")

        self.chat_label = tkinter.Label(self.win, text="chat", bg="lightgray")
        self.chat_label.config(font=("arial", 12))
        self.chat_label.pack(padx=20, pady=5)

        self.text_area = tkinter.scrolledtext.ScrolledText(self.win)
        self.text_area.pack(padx=20, pady=5)
        self.text_area.config(state='disabled')

        self.msg_label = tkinter.Label(self.win, text="message", bg="lightgray")
        self.msg_label.config(font=("arial", 12))
        self.msg_label.pack(padx=20, pady=5)

        self.input_area = tkinter.Text(self.win, height =3)
        self.input_area.pack(padx=20,pady=5)

        self.send_button = tkinter.Button(self.win, text="send", command=self.write)
        self.send_button.config(font=("arial", 12))
        self.send_button.pack(padx=20, pady=5)

        self.gui_done = True
        self.win.protocol("WM_DELETE_WINDOW", self.stop)
        self.win.mainloop()

    def write(self):
        message = f"{self.nickname}:{self.input_area.get('1.0', 'end')}"
        self.sock.send(message.encode('utf-8'))
        self.input_area.delete('1.0', 'end')

    def stop(self):
        self.running = False
        self.win.destroy()
        self.sock.close()
        exit(0)

    def receive(self):
        while self.running:
            try:
                message = self.sock.recv(1024).decode('utf-8')
                if message=='NICK':
                    self.sock.send(self.nickname.encode('utf-8'))
                else:
                    if self.gui_done:
                        self.text_area.config(state='normal')
                        self.text_area.insert('end', message)
                        self.text_area.yview('end')
                        self.text_area.config(state='disabled')
            except ConnectionAbortedError:
                break
            except:
                print("error")
                self.sock.close()
                break


client = Client(HOST, PORT) 

服务器文件是

import socket
import threading

HOST = '127.0.0.1'
PORT = 9091

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(client):
    while True:
        try:
            message = client.recv(1024).decode('utf-8')
            print(f"{nicknames[client.index(client)]})")
            broadcast(message)
        except:
            index = clients.index(client)
            clients.remove(client)
            client.close()
            nickname = nicknames[index]
            nicknames.remove(nickname)
            break


def receive():
    while True:
        client, address = server.accept()
        print(f"connected with {str(address)}!")

        client.send("NICK".encode('utf-8'))
        nickname = client.recv(1024)

        nicknames.append(nickname)
        clients.append(client)

        print(f"nicknames of client is {nickname}")
        broadcast(f"{nickname} connected successfully!\n".encode('utf-8'))
        client.send("connected to the server".encode('utf-8'))

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


print("server running")
receive()

我尝试搜索,但我没有看到有人遇到这个问题,我认为没有任何编程错误

如果有人知道出了什么问题,请告诉我。 谢谢

【问题讨论】:

  • 首先,在您的客户端中,您永远不会破坏msg 窗口。其次,您不应该从创建tk.Tk() 窗口的线程以外的线程访问tkinter 小部件/函数。第三,这个问题看起来像一个socket 的错误问题。如果我是正确的,请从问题中删除tkinter 标签。
  • 我在 init 中的 tkinter 中也出现错误,如错误框中所示
  • 您使用了command=self.write,因此在来自tkinter/__init__.py 的回溯中将显示为return self.func(*args)。实际错误来自socket.write(...)
  • 也许首先使用print() 来查看执行了哪一行代码以及变量中有什么。它被称为"print debuging"。也许代码看起来是正确的,但你可能会以错误的顺序运行函数,双方可能同时等待消息,然后它就会出现问题。
  • 你不必在f-string中使用str()

标签: python python-3.x sockets tkinter


【解决方案1】:

您最大的错误是except: 没有打印有关问题的信息。

我用

except Exception as ex: 
    print (ex)
    # ... rest ...

首先它显示给我

 'socket' object has no attribute 'index'

因为你忘记了s in word clients in line

print(f"{nicknames[clients.index(client)]})")

接下来它告诉我

a bytes-like object is required, not 'str' 

因为你在下一行发送str 而不是bytes - 你需要encode()

broadcast(message.encode('utf-8'))

在这些更改之后,它开始为我工作。


def handle(client):
    while True:
        try:
            message = client.recv(1024).decode('utf-8')  # convert bytes to string
            print(f"{nicknames[clients.index(client)]})")  # forgot `s`
            broadcast(message.encode('utf-8'))  # convert string back to bytes
        except Exception as ex:
            print('Exception:', ex)

            index = clients.index(client)
            clients.remove(client)
            client.close()
            nickname = nicknames[index]
            nicknames.remove(nickname)
            break

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多