本文共 5703 字,大约阅读时间需要 19 分钟。
聊天应用程序是许多开发者入门的经典项目之一。通过合理利用多线程和网络编程,我们可以在短短几百行代码中完成一个功能齐全的聊天系统。以下将详细介绍如何从零开始,逐步搭建一个无依赖的聊天应用程序。
服务器端的主要功能包括接收客户端连接、处理消息广播以及管理客户端会话。我们使用标准的socket
库和多线程技术来实现这一点。
from socket import AF_INET, socket, SOCK_STREAMfrom threading import Thread
BUFSIZ = 1024 # 数据传输缓冲大小ADDR = (HOST, PORT) # 服务器地址和端口
def accept_incoming_connections(): while True: client, client_address = SERVER.accept() print(f"{client_address} has connected.") client.send("欢迎来到聊天室!请输入你的名字并按回车。".encode("utf-8")) addresses[client] = client_address Thread(target=handle_client, args=(client,)).start()
def handle_client(client): name = client.recv(BUFSIZ).decode("utf-8") welcome = f"欢迎 {name}!输入 {quit} 退出。" client.send(welcome.encode("utf-8")) broadcast(f"{name} 已加入聊天。", name) clients[client] = name while True: msg = client.recv(BUFSIZ) if not msg: break if msg.decode("utf-8") == "{quit}": client.send("{quit}".encode("utf-8")) client.close() del clients[client] broadcast(f"{name} 已离开聊天。", name) break broadcast(f"{name}: {msg.decode('utf-8')}", name)
def broadcast(msg, prefix=""): for sock in clients: sock.send(f"{prefix}{msg}".encode("utf-8"))
if __name__ == "__main__": SERVER.listen(5) print("正在侦听连接...") accept_thread = Thread(target=accept_incoming_connections) accept_thread.start() accept_thread.join() SERVER.close()
客户端使用Tkinter库创建GUI界面,支持消息发送和接收。
from socket import AF_INET, socket, SOCK_STREAMfrom threading import Threadimport tkinter
top = tkinter.Tk()top.title("聊天室")messages_frame = tkinter.Frame(top)my_msg = tkinter.StringVar()my_msg.set("输入你的消息。")
msg_list = tkinter.Listbox(messages_frame, height=15, width=50, yscrollcommand=scrollbar.set)scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)msg_list.pack(side=tkinter.LEFT, fill=tkinter.BOTH)msg_list.pack()messages_frame.pack()
entry_field = tkinter.Entry(top, textvariable=my_msg)entry_field.bind("", send)entry_field.pack()send_button = tkinter.Button(top, text="发送", command=send)send_button.pack()
HOST = input("请输入服务器地址:")PORT = input("请输入服务器端口:")if not PORT: PORT = 33000ADDR = (HOST, PORT)client_socket = socket(AF_INET, SOCK_STREAM)client_socket.connect(ADDR)receive_thread = Thread(target=receive)receive_thread.start()tkinter.mainloop()
#!/usr/bin/env python3from socket import AF_INET, socket, SOCK_STREAMfrom threading import ThreadBUFSIZ = 1024ADDR = (input("请输入服务器地址:"), int(input("请输入服务器端口:") or 33000))SERVER = socket(AF_INET, SOCK_STREAM)SERVER.bind(ADDR)def accept_incoming_connections(): while True: client, client_address = SERVER.accept() print(f"{client_address} 已连接。") client.send("欢迎来到聊天室!请输入你的名字并按回车。".encode("utf-8")) addresses[client] = client_address Thread(target=handle_client, args=(client,)).start()def handle_client(client): name = client.recv(BUFSIZ).decode("utf-8") welcome = f"欢迎 {name}!输入 {quit} 退出。" client.send(welcome.encode("utf-8")) broadcast(f"{name} 已加入聊天。", name) clients[client] = name while True: msg = client.recv(BUFSIZ) if not msg: break if msg.decode("utf-8") == "{quit}": client.send("{quit}".encode("utf-8")) client.close() del clients[client] broadcast(f"{name} 已离开聊天。", name) break broadcast(f"{name}: {msg.decode('utf-8')}", name)def broadcast(msg, prefix=""): for sock in clients: sock.send(f"{prefix}{msg}".encode("utf-8"))if __name__ == "__main__": SERVER.listen(5) print("正在侦听连接...") accept_thread = Thread(target=accept_incoming_connections) accept_thread.start() accept_thread.join() SERVER.close()
#!/usr/bin/env python3from socket import AF_INET, socket, SOCK_STREAMfrom threading import Threadimport tkintertop = tkinter.Tk()top.title("聊天室")messages_frame = tkinter.Frame(top)my_msg = tkinter.StringVar()my_msg.set("输入你的消息。")scrollbar = tkinter.Scrollbar(messages_frame)msg_list = tkinter.Listbox(messages_frame, height=15, width=50, yscrollcommand=scrollbar.set)scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)msg_list.pack(side=tkinter.LEFT, fill=tkinter.BOTH)msg_list.pack()messages_frame.pack()entry_field = tkinter.Entry(top, textvariable=my_msg)entry_field.bind("", send)entry_field.pack()send_button = tkinter.Button(top, text="发送", command=send)send_button.pack()top.protocol("WM_DELETE_WINDOW", on_closing)def send(event=None): msg = my_msg.get() my_msg.set("") if msg.strip() == "{quit}": client_socket.close() top.quit() else: client_socket.send(msg.encode("utf-8")) if msg: broadcast(msg, my_msg.get())def on_closing(event=None): my_msg.set("{quit}") send()HOST = input("请输入服务器地址:")PORT = int(input("请输入服务器端口:") or 33000)ADDR = (HOST, PORT)client_socket = socket(AF_INET, SOCK_STREAM)client_socket.connect(ADDR)def receive(): while True: try: msg = client_socket.recv(BUFSIZ).decode("utf-8") msg_list.insert(tkinter.END, msg) except OSError: breakreceive_thread = Thread(target=receive)receive_thread.start()tkinter.mainloop()
通过以上代码,我们可以轻松搭建一个功能齐全的聊天应用程序。服务器端支持多人在线聊天,客户端提供友好的GUI界面。整个系统不依赖任何第三方库,完全由标准Python库驱动,实现了高效的消息传输和多线程处理。
转载地址:http://vhybz.baihongyu.com/