python+socket实现多人聊天室,功能:好友聊天、群聊、图片、表情、文件等源码
时间: 2023-06-05 10:02:19 浏览: 262
Python实现的多人聊天室源码,基于socket tcp通信,使用tkinter做客户端界面,含可执行文件
5星 · 资源好评率100%
Python Socket是Python编程语言标准库的一部分,用于网络通信,在Python socket中实现多人聊天室需要以下步骤:
1. 创建一个服务器Socket和一个客户端Socket,分别负责监听和连接。
2. 在服务器端设置一个线程或进程,负责监听所有连接并接受任何来自客户端的消息。在客户端端设置一个线程或进程,负责发送消息和接收来自服务器的消息。
3. 建立一个数据结构保存所有连接的客户端套接字,以及每个客户端的IP地址和端口号。
4. 实现好友聊天和群聊功能,对于需要多个接收者的消息组合来发送,并在每个接收者的客户端显示消息。
5. 实现图片和表情功能,将图像数据编码为字节流并将其发送到所有客户端。
6. 实现文件传输功能,将文件分成小块并逐个发送,以便所有客户端都能够接收到。
示例代码如下:
server.py:
import socket
import threading
# 设置主机和端口号
host = "127.0.0.1"
port = 9999
# 创建Socket实例并监听端口号
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen()
# 保存所有连接的客户端
clients = []
def broadcast(message):
"""
向所有客户端广播消息
"""
for client in clients:
client.send(message)
def handle_client(client):
"""
处理客户端消息
"""
while True:
try:
message = client.recv(1024)
broadcast(message)
except:
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
broadcast(f"{nickname}离开聊天室!".encode("utf-8"))
nicknames.remove(nickname)
break
def receive():
"""
监听所有连接,接受客户端信息
"""
while True:
client, address = server.accept()
print(f"已连接到:{str(address)}")
# 保存客户端套接字和昵称
client.send("请输入昵称:".encode("utf-8"))
nickname = client.recv(1024).decode("utf-8")
nicknames.append(nickname)
clients.append(client)
# 输出已连接客户端昵称
print(f"昵称:{nickname}")
broadcast(f"{nickname}加入聊天室!".encode("utf-8"))
client.send("已成功连接到聊天室!".encode("utf-8"))
# 创建新线程处理该客户端
thread = threading.Thread(target=handle_client, args=(client,))
thread.start()
if __name__ == "__main__":
print("聊天室服务器已开启,请等待连接!")
receive()
client.py:
import socket
import threading
import tkinter
from tkinter import ttk, scrolledtext, messagebox
from tkinter.filedialog import askopenfilename
from PIL import Image, ImageTk
import os
nickname = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def receive():
"""
接受服务端消息
"""
while True:
try:
message = s.recv(1024).decode("utf-8")
if message == "请输入昵称:":
s.send(nickname.encode("utf-8"))
else:
print(message)
add_to_chat(message)
except:
print("发生错误!")
s.close()
break
def send(event=None):
"""
发送消息到服务器
"""
message = my_msg.get()
if message != "":
s.send(message.encode("utf-8"))
my_msg.set("")
if message == "{quit}":
s.close()
root.quit()
def add_to_chat(message):
"""
在聊天室窗口中添加新消息
"""
chat_box.configure(state="normal")
chat_box.insert("end", message + "\n")
chat_box.configure(state="disabled")
chat_box.see("end")
def choose_file():
"""
弹出对话框选择文件
"""
file = askopenfilename()
if file:
filename = os.path.basename(file)
add_to_chat(f"{nickname}发送了文件:{filename}")
filesize = os.path.getsize(file)
# 发送文件头信息
s.send(f"FILE {filename} {filesize}".encode("utf-8"))
# 分块发送文件
with open(file, "rb") as f:
while True:
data = f.read(1024)
if not data:
break
s.sendall(data)
def choose_image():
"""
弹出对话框选择图片
"""
file = askopenfilename()
if file:
image = Image.open(file)
photo = ImageTk.PhotoImage(image)
chat_box.image_create("end", image=photo)
# 发送图像数据
with open(file, "rb") as f:
bytes_img = f.read()
s.sendall(bytes_img)
def init_send_frame():
"""
创建发送消息区域
"""
send_frame = ttk.Frame(root)
send_frame.pack(fill="x")
global my_msg
my_msg = tkinter.StringVar()
my_msg.set("在这里输入您的消息")
entry_field = ttk.Entry(send_frame, textvariable=my_msg)
entry_field.bind("<Return>", send)
entry_field.pack(side="left", fill="x", expand=True)
send_button = ttk.Button(send_frame, text="发送", command=send)
send_button.pack(side="right")
send_file_button = ttk.Button(send_frame, text="选择文件", command=choose_file)
send_file_button.pack(side="left")
send_image_button = ttk.Button(send_frame, text="选择图片", command=choose_image)
send_image_button.pack(side="left")
def init_chat_frame():
"""
创建聊天室区域
"""
chat_frame = ttk.Frame(root)
chat_frame.pack(fill="both", expand=True)
global chat_box
chat_box = tkinter.scrolledtext.ScrolledText(chat_frame)
chat_box.pack(side="left", fill="both", expand=True)
def start_chat():
"""
启动聊天室
"""
# 获取昵称
global nickname
nickname = simpledialog.askstring("昵称", "请输入您的聊天室昵称:", parent=root)
# 连接到服务器
host = "localhost"
# 端口号需与服务器端开启端口号相同
port = 9999
s.connect((host, port))
add_to_chat(f"您已成功连接到聊天室: {host}:{port}")
s.send(nickname.encode("utf-8"))
thread = threading.Thread(target=receive)
thread.start()
root = tkinter.Tk()
root.title("聊天室")
root.geometry("600x400")
init_chat_frame()
init_send_frame()
start_chat()
root.mainloop()
阅读全文