python套接字客户端未从服务器接收消息

问题描述 投票:0回答:1

这是我第一次在这个网站上问问题,尽管我使用了这里的很多信息,所以我可能不是最擅长问这些问题的 不管怎样,我正在尝试制作一个套接字 tkinter 程序,让一个用户输入一条消息并将其发送回每个人。我肯定还没有完成,但我有一个问题,在我连接到服务器并发送消息然后等待消息返回后,程序窗口冻结并停止响应,而不是返回。这很可能是由于 tkinter 无法更新,因为它正在等待套接字消息,这意味着服务器无法发送消息。这是代码:

客户:

# echo-client.py
import socket
import tkinter as tk
from threading import Thread
snd = False
win = tk.Tk()
win.geometry("365x230")
win.title("chat")
mmsg = ""
conc = False
conn = False
HOST = "192.168."  # The server's hostname or IP address
PORT = 0  # The port used by 453 server

def savemsg(event=None):
    global mmsg
    global conc
    if conc:
        mmsg = msg.get()
        msg.delete(0,tk.END)
        snd = True
        print("test1")
        s.sendall(mmsg.encode("utf8"))
        print("test2")
        data = s.recv(1024)
        print("test3")
        if data:
            msgtxt.insert(0, (f"{data!r}"[2:-1]))
def LoginWindow():
    global lw
    global HOST
    global PORT
    global welc

    def connect(event=None):
        global HOST
        global PORT
        global welc
        global conc
        try:
            eval(portb.get())
            HOST = addb.get()
            PORT = eval(portb.get())
            if not conc:
                try:
                    s.connect((HOST,PORT))
                    conn = False
                    lw.destroy()
                    conc = True

                except ConnectionRefusedError:
                    welc.config(text="Server is not open")
                    conn = False
                except socket.gaierror:
                    welc.config(text="Invalid address!")
                    conn = False
        except:
            welc.config(text="Invalid port!")

    try:
        lw.destroy()
    except NameError:
        pass
    lw = tk.Toplevel()
    lw.geometry("300x250") 
    lw.title("connect")
    welc = tk.Label(lw, text="Connect to a server", font=("Arial", 20))
    txtf = tk.Frame(lw, height=3)
    inputf = tk.Frame(lw, height=3)
    addt = tk.Label(txtf, text="address:", height=1, width=30)
    portt = tk.Label(txtf, text="port:", height=1, width=16)
    addb = tk.Entry(inputf, width=30)
    portb = tk.Entry(inputf, width=16)
    connbtn = tk.Button(lw, text="Connect", height=1, width=6, command=connect)
    welc.pack(side="top", expand=True)
    txtf.pack(side="top", expand=True, fill="x")
    inputf.pack(side="top", expand=True, fill="x")
    addt.pack(side="left", expand=True)
    portt.pack(side="right", expand=True)
    addb.pack(side="left", expand=True)
    portb.pack(side="right", expand=True)
    connbtn.pack(side="bottom", expand=True)
    addb.insert(0, HOST)
    portb.insert(0, str(PORT))

chtxt = tk.Label(text="Chat on socket!", width=15, height=5)
sendframe = tk.Frame(win, height=3, width=10)
sndbtn = tk.Button(sendframe, text="Send!", width=10, height=1)
msg = tk.Entry(sendframe, width=50)
msgtxt = tk.Listbox(width=25, height=7)
scrl = tk.Scrollbar(win, command=msgtxt.yview)
cncb = tk.Button(text="connect", width=6, height=1)
sendframe.pack(side="bottom", expand=True)
chtxt.pack(side="top", expand=True)
cncb.pack(side="top", expand=True)
scrl.pack(side="right", expand=True, anchor="e", fill="y")
msgtxt.pack(expand=True, side="left", anchor="e")
sndbtn.pack(side="right", expand=True)
msg.pack(side="left", expand=True)
msgtxt.config(yscrollcommand=scrl.set)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cncb.config(command=LoginWindow)
sndbtn.config(command=savemsg)
win.bind("<Return>", savemsg)
snd = False
def upd():
    global snd
    while True:
        try:
            if snd == True:    
                s.sendall(mmsg.encode("utf8"))
                print(mmsg)
                snd = False
        except UnboundLocalError:
            snd = bool
            if snd == True:    
                s.sendall(mmsg.encode("utf8"))
                print(mmsg)
                snd = False

def func2():
    global conc
    while True:
        if conc:
            data = s.recv(1024)
            if data:
                msgtxt.insert(1, (f"{data!r}"[2:-1]))
thread = Thread(target = func2, daemon=True)
thread.start()
win.mainloop()

服务器:

# echo-server.py

import socket
from threading import Thread

connections = []

def gethighest(nums=[]):
    h = 0
    for i in nums:
        if i > h:
            h = i
    return h


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
    print("current ip is ", socket.gethostname())
    HOST = input("address: \n")
    PORT = int(input("port: \n"))  # Port to listen on (non-privileged ports are > 1023)
    try:
        s.bind((HOST, PORT))
        print("Server opened")
        break
    except:
        print("invalid!")
def connecc(conn, addr):
    with conn:
        print(f"Connected by {addr}")
        sendtoall("user connected".encode("utf-8"))
        while True:
            try:
                data = conn.recv(1024)
                if data:
                    print(data)
                    sendtoall(data)
            except ConnectionError:
                print("user disconnnected")
                break
def sendtoall(message):
    global connections
    for c in connections:
        c[0].sendall(message)
        print("sent")
while True:
    s.listen()  
    conn, addr = s.accept()
    connections.append([conn, addr, Thread(target=connecc, daemon=True, args=(conn, addr))])
    connections[len(connections)-1][2].start()

消息应该在客户端上接收回来,但客户端可能因服务器代码编写不正确或无法发送而挂起

python python-3.x sockets tkinter
1个回答
0
投票

您似乎面临这样的问题:发送消息后客户端的 GUI 冻结,可能是由于等待服务器的响应。这种冻结可能是由于客户端的代码结构和缺乏处理套接字通信的线程造成的。

为了解决这个问题,您可以修改客户端的代码以使用线程从服务器发送和接收消息。这样,GUI 在等待响应时就不会冻结。以下是如何构建代码的基本概述:

  1. 创建单独的函数来发送和接收消息。
  2. 使用线程与 GUI 同时运行这些函数。

以下是如何修改客户端代码的简化示例:

import socket
import tkinter as tk
from threading import Thread

# Global variables
HOST = "192.168."
PORT = 0
s = None

def send_message(message):
    global s
    try:
        s.sendall(message.encode("utf8"))
    except Exception as e:
        print("Error:", e)

def receive_messages():
    global s
    while True:
        try:
            data = s.recv(1024)
            if data:
                # Update GUI with received message
                msgtxt.insert(tk.END, data.decode("utf-8"))
        except Exception as e:
            print("Error:", e)
            break

def savemsg(event=None):
    # Function to send message from GUI
    message = msg.get()
    send_message(message)
    msg.delete(0, tk.END)

# GUI setup
win = tk.Tk()
# ... (GUI setup code)

# Connect to server function
def connect():
    global s
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((HOST, PORT))
        # Start a thread to receive messages from the server
        receive_thread = Thread(target=receive_messages, daemon=True)
        receive_thread.start()
    except Exception as e:
        print("Error:", e)

# Button to connect to server
cncb = tk.Button(text="Connect", width=6, height=1, command=connect)
# ... (more GUI code)

# Start GUI main loop
win.mainloop()

这只是一个演示该想法的基本示例。您需要将其与现有代码集成并适当处理错误。此外,请记住在关闭应用程序时正确处理关闭套接字连接。

© www.soinside.com 2019 - 2024. All rights reserved.