我想做什么:
我想用python在服务器和多个客户端之间编写某种使者程序。我有一个运行有套接字库的服务器,我可以获取用户的输入并将其发送回用户。我的问题是,我希望能够在打印出新消息时进行键入。
我的问题:
当我打印出新消息时,我无法在控制台中键入任何内容,当我得到一个带有tkinter编程的简单gui时,它只会变直并且不会响应并崩溃。我知道问题出在client.py中的get_message
函数中。
我的代码:
是的,我知道这不是最好,最有效的方法,但是对我有用。
任何帮助都是有帮助的。
server.py
import socket
import threading
import pickle
HEADER = 64
PORT = 5050
update_message_char = "update_messages_char"
SERVER = "0.0.0.0" # it's using my virtualbox host-only adapter, which i don't want:
# socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!disconnect"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
usernames = {}
author = []
messages = []
forbidden_chars = ["message_update", "update_messages_char"]
def handle_client(conn, addr):
print(f"New Connection: {addr} connected\n")
username_received = conn.recv(HEADER).decode(FORMAT)
if addr not in usernames.keys():
if username_received:
username_received = int(username_received)
username = conn.recv(username_received).decode(FORMAT)
usernames[addr] = username
print(f"{addr} has got the username {username}")
connected = True
while connected:
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
print(f"{usernames[addr]} said: {msg}")
if msg == DISCONNECT_MESSAGE:
connected = False
elif msg == update_message_char:
author_list = pickle.dumps(author)
message_list = pickle.dumps(messages)
conn.send(author_list)
conn.send(message_list)
elif msg not in forbidden_chars:
messages.append(msg)
author.append(usernames[addr])
conn.close()
print(f"Connection to {usernames[addr]} closed")
def start():
server.listen()
print(f"Server is listening on {SERVER}")
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"Active Connections {threading.activeCount() -1}")
print(f"Server is starting on port {PORT}")
start()
client.py:
import socket
import time
import pickle
import threading
import tkinter as tk
HEIGHT = 800
WIDTH = 1200
update_message_char = "update_messages_char"
HEADER = 64
PORT = 5050
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!disconnect"
SERVER = "192.168.0.18"
ADDR = (SERVER, PORT)
counter = 0
messages = []
author = []
old_messages = []
old_authors = []
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)
def send(msg):
if msg == DISCONNECT_MESSAGE:
disconnect()
elif msg == "update_message":
thread = threading.Thread(target=get_messages())
thread.start()
else:
message = msg.encode(FORMAT)
msg_length = len(message)
send_length = str(msg_length).encode(FORMAT)
send_length += b' ' * (HEADER - len(send_length))
client.send(send_length)
client.send(message)
def disconnect():
print("You will be disconnected from the server and the program will close")
message = f"{DISCONNECT_MESSAGE}".encode(FORMAT)
msg_length = len(message)
send_length = str(msg_length).encode(FORMAT)
send_length += b' ' * (HEADER - len(send_length))
client.send(send_length)
client.send(message)
exit()
def setup_username():
username = input("Please type in your username: ")
username = username.encode(FORMAT)
username_length = len(username)
send_length = str(username_length).encode(FORMAT)
send_length += b' ' * (HEADER - len(send_length))
client.send(send_length)
client.send(username)
def get_messages():
global counter
send(update_message_char)
author_list = pickle.loads(client.recv(2048))
message_list = pickle.loads(client.recv(2048))
if counter == 0:
for i in author_list:
author.append(i)
for i in message_list:
messages.append(i)
counter += 1
elif counter == 1:
for i in author:
old_authors.append(i)
for i in messages:
old_messages.append(i)
for i in author:
author.remove(i)
for i in messages:
messages.remove(i)
for i in author_list:
author.append(i)
for i in message_list:
messages.append(i)
list1 = set(messages)
list2 = set(old_messages)
list3 = list1.difference(list2)
time.sleep(4)
get_messages()
def gui():
root = tk.Tk()
root.title("Messaging service lol")
canvas = tk.Canvas(root, height=HEIGHT, width=WIDTH)
canvas.pack()
frame = tk.Frame(root, bg="black", bd=5)
frame.place(relwidth=1, relheight=0.1, relx=0.5, rely=0.0001, anchor="n")
button = tk.Button(root, text="Send", bg="#041982", fg="black", font=40, command=lambda: send(entry.get()))
button.place(relx=0.8, rely=0.0001, relwidth=0.2, relheight=0.1)
c1 = tk.Button(frame, text="Exit", bg="#041982", font=20, command=disconnect)
c1.place(relx=0.7, rely=0.0001, relwidth=0.1, relheight=0.3)
entry = tk.Entry(frame, bg="#404040")
entry.place(relx=0.3, rely=0.4, relwidth=0.25, relheight=0.4)
lower_frame = tk.Frame(root, bg="black")
lower_frame.place(relx=0.5, rely=0.1, relwidth=1, relheight=0.9, anchor="n")
label = tk.Label(lower_frame, bg="black", fg="red", anchor="nw", justify="left", font=20)
label.place(relwidth=0.8, relheight=0.8, relx=0.1, rely=0.1)
root.mainloop()
setup_username()
print(f"You are connected to the server!\nIf you want to disconnect, simply type {DISCONNECT_MESSAGE}")
thread = threading.Thread(target=gui)
thread.start()