这是tkinter套接字Python聊天室,用户可以在其中相互发送消息。
我遇到的问题是,当我使用此代码时:
kick = input("Enter address you want to kick: ")
if addr[0] != kick:
conn.close()
第一次踢用户,但是当我尝试再次使用它时,kick
输入不会显示。所以我想要的是,在一个用户被踢后,我希望它给我一个选择来踢另一个用户。
import socket, threading, json
host = "127.0.0.1"
port = 4000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen()
clients = {}
addresses = {}
print(host)
print("Server is ready...")
serverRunning = True
def to_json(p):
return bytes(json.dumps(p), "utf8")
def handle_client(conn):
try:
user_name = conn.recv(1024).decode('utf8')
conn.send(to_json({'CONNECTED':user_name, 'JOINED':list(clients.values())}))
#welcome = 'Welcome %s! If you ever want to quit, type {quit} to exit.' % user_name
#conn.send(bytes(welcome, "utf8"))
#msg = "%s has joined the chat" % user_name
broadcast(to_json({'JOINED':user_name}))
clients[conn] = user_name
while True:
found = False
msg = conn.recv(1024)
if msg != bytes("{quit}" or '**', "utf8"):
broadcast(msg, user_name+": ")
else:
conn.send(bytes("{quit}", "utf8"))
conn.close()
del clients[conn]
broadcast(to_json({'DISJOINED':user_name}))
print("%s has left the chat." % user_name)
break
if user_name in clients.values():
conn.send("username has been taken")
else:
continue
except Exception as e:
print('Exception: {} while connected with user: {}'.format(e, user_name))
def broadcast(msg, prefix=""):
for sock in clients:
sock.send(bytes(prefix, "utf8")+msg)
while True:
conn,addr = s.accept()
conn.send("You have connected to the server \r\n ".encode("utf8"))
conn.send("Enter username: ".encode("utf8"))
print("%s:%s has connected." % addr)
addresses[conn] = addr
threading.Thread(target = handle_client, args = (conn,)).start()
kick = input("Enter address you want to kick: ")
if addr[0] != kick:
conn.close()
import socket,threading,tkinter,json,winsound
tk = tkinter
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def echo_data(sock):
while True:
try:
msg = sock.recv(1024).decode('utf8')
if msg[0] == '{': # JSON Message
message = json.loads(msg)
# We don't have the `app` object, therefore you have to handle the message here
if 'CONNECTED' in message:
msg_list.insert(tkinter.END, "Welcome {} If you ever want to quit, type quit to exit".format(message['CONNECTED']))
users_online.connected(message)
elif 'JOINED' in message:
msg_list.insert(tkinter.END, "{} has joined the chat.".format(message['JOINED']))
users_online.joined(message)
elif 'DISJOINED' in message:
msg_list.insert(tkinter.END, "{} has left the chat.".format(message['DISJOINED']))
users_online.disjoined(message)
else:
print('FAIL: Unknow Message {}'.format(message))
else:# TEXT Message
msg_list.insert(tkinter.END, msg)
except OSError:
print('Terminate thread echo_data')
msg_list.insert(tkinter.END, "Connection got closed, for unknown reason, try to reconnect.")
connect_button.configure(state=['normal'])
entry_field.configure(state=['disabled'])
send_button.configure(state=['disabled'])
return
def send(event=None):
try:
msg = my_msg.get()
my_msg.set("")
s.send(bytes(msg, "utf8"))
if msg == "{quit}":
s.close()
top.quit()
except Exception:
top.quit()
pass
def on_closing(event=None):
my_msg.set("{quit}")
send()
def connect():
port = 4000
send_button.configure(state=['normal'])
connect_button.configure(state=['disabled'])
entry_field.configure(state=['normal'])
print('Server address:{}'.format(entry_server_address.get()))
host = entry_server_address.get()
address = (host,port)
s.connect(address)
threading.Thread(target=echo_data, args = (s,)).start()
class LabelFrame(tk.LabelFrame):
def __init__(self, parent, text):
self._width = 100
self._bg = 'white'
super().__init__(parent, text=text, width=self._width, background=self._bg)
self.pack(side=tk.RIGHT, fill=tk.Y)
def joined(self, message):
global user_online
print('joined({})'.format(message))
# Add a `tk.Label(self, ...` and assign `text=<username>`
user_online = tk.Label(self, text=message['JOINED'],bg=self._bg)
user_online.grid(row=None, column=None)
def connected(self, message):
print('connected({})'.format(message))
tk.Label(self, text=message['CONNECTED'], bg=self._bg).grid()
if 'JOINED' in message:
for user_name in message['JOINED']:
tk.Label(self, text=user_name, bg=self._bg).grid()
def disjoined(self, message):
print('disjoined({})'.format(message))
for lbl in self.grid_slaves():
if lbl['text'] in message.values():
lbl.destroy()
top = tkinter.Tk()
top.title("Chat Room")
messages_frame = tkinter.Frame(top)
my_msg = tkinter.StringVar()
my_msg.set("Type your messages here.")
scrollbar = tkinter.Scrollbar(messages_frame)
msg_list = tkinter.Listbox(messages_frame, height=15, width=100, yscrollcommand=scrollbar.set)
scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
msg_list.pack(side=tkinter.LEFT, fill=tkinter.BOTH)
users_online = LabelFrame(messages_frame, 'Users online:')
messages_frame.pack()
entry_field = tkinter.Entry(top, textvariable=my_msg)
entry_field.configure(state='disabled')
entry_field.bind("<Return>", send)
entry_field.pack()
send_button = tkinter.Button(top, text="Send", command=send)
send_button.configure(state=['disabled'])
send_button.pack()
le_frame = tkinter.Frame(top)
le_frame.pack(fill=tkinter.X)
entry_server_address = tkinter.Entry(le_frame)
tkinter.Label(le_frame, text='Server address:', width=20, anchor='w').pack(side=tkinter.LEFT, padx=5)
entry_server_address.pack(side=tkinter.LEFT, fill=tkinter.X, expand=True, padx=5)
connect_button = tkinter.Button(le_frame, text='Connect', command=connect)
connect_button.pack(side=tkinter.LEFT, padx=5)
top.protocol("WM_DELETE_WINDOW", on_closing)
tkinter.mainloop()
答案 0 :(得分:1)
它在线程中运行accept()
,而input()
在while True
中正常运行
这样,线程中的循环可以接受许多客户端,而普通循环可以运行input()
并等待答案。我使用端口而不是地址将连接保持在列表中并踢人。 port
更好,因为两个用户不能具有相同的端口,但是他们可能具有sam地址-即。您可以在计算机的两个终端上运行两个客户端,它们的地址相同,但端口始终不同。
编辑:连接有效,您可以启动某人,但是在发送之前可能需要将字符串编码为字节,并在接收到字符串时将其从字节解码为字符串。
import socket, threading, json
host = "127.0.0.1"
port = 4000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen()
clients = {}
addresses = {}
print(host)
print("Server is ready...")
serverRunning = True
def to_json(p):
return bytes(json.dumps(p), "utf8")
def handle_client(conn):
try:
user_name = conn.recv(1024).decode('utf8')
conn.send(to_json({'CONNECTED':user_name, 'JOINED':list(clients.values())}))
#welcome = 'Welcome %s! If you ever want to quit, type {quit} to exit.' % user_name
#conn.send(bytes(welcome, "utf8"))
#msg = "%s has joined the chat" % user_name
broadcast(to_json({'JOINED':user_name}))
clients[conn] = user_name
while True:
found = False
msg = conn.recv(1024)
if msg != bytes("{quit}" or '**', "utf8"):
broadcast(msg, user_name+": ")
else:
conn.send(bytes("{quit}", "utf8"))
conn.close()
del clients[conn]
broadcast(to_json({'DISJOINED':user_name}))
print("%s has left the chat." % user_name)
break
if user_name in clients.values():
conn.send("username has been taken")
else:
continue
except Exception as e:
print('Exception: {} while connected with user: {}'.format(e, user_name))
def broadcast(msg, prefix=""):
for sock in clients:
sock.send(bytes(prefix, "utf8")+msg)
#--- new code ---
addresses = dict()
def loop():
while True:
conn,addr = s.accept()
conn.send("You have connected to the server \r\n ".encode("utf8"))
conn.send("Enter username: ".encode("utf8"))
print("%s:%s has connected." % addr)
addresses[addr[1]] = (addr,conn)
threading.Thread(target=handle_client, args=(conn,)).start()
threading.Thread(target=loop).start()
while True:
print(addresses.keys())
port = int(input('port> '))
if port in addresses:
addresses[port][1].close()
print('kick:', addresses[port][0])