本帖最后由 李承键 于 2025-2-16 17:30 编辑
[C++] 纯文本查看 复制代码 import socket
import threading
# 服务器配置
HOST = '127.0.0.1'
PORT = 58588
# 创建 TCP 套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen()
# 存储所有连接的客户端
clients = []
nicknames = []
# 广播消息给所有客户端
def broadcast(message):
for client in clients:
client.send(message)
# 发送在线用户列表给所有客户端
def send_online_users():
users_str = ','.join(nicknames)
message = f'USERS{users_str}'.encode('utf-8')
broadcast(message)
# 处理客户端连接
def handle(client):
while True:
try:
# 接收客户端消息
message = client.recv(1024)
if not message:
break
broadcast(message)
except:
# 处理客户端断开连接
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
nicknames.remove(nickname)
broadcast(f'{nickname} 离开了聊天室!'.encode('utf-8'))
send_online_users()
break
# 接收新的客户端连接
def receive():
while True:
client, address = server_socket.accept()
print(f'连接地址: {str(address)}')
# 发送昵称请求
client.send('NICK'.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'))
send_online_users()
# 为每个客户端创建一个线程来处理消息
thread = threading.Thread(target=handle, args=(client,))
thread.start()
print("服务器正在监听...")
receive()
import socket
import threading
import tkinter as tk
from tkinter import simpledialog, messagebox
from tkinter import scrolledtext
import winsound # 用于播放提示音,仅适用于Windows系统
# 全局变量
client = None
nickname = None
online_users = []
# 接收服务器消息
def receive():
global online_users
while True:
try:
# 接收服务器消息
message = client.recv(1024).decode('utf-8')
if message.startswith('NICK'):
client.send(nickname.encode('utf-8'))
elif message.startswith('USERS'):
# 更新在线用户列表
users_str = message[6:]
online_users = users_str.split(',')
update_user_list()
else:
chat_box.insert(tk.END, message + '\n')
# 播放提示音
winsound.Beep(500, 200)
except:
# 发生错误,关闭连接
messagebox.showerror("错误", "与服务器的连接已断开!")
client.close()
break
# 发送消息到服务器
def send_message(event=None):
message = input_box.get()
input_box.delete(0, tk.END)
if message:
client.send(f'{nickname}: {message}'.encode('utf-8'))
# 连接到服务器
def connect():
global client, nickname
server_ip = ip_entry.get()
if not server_ip:
messagebox.showerror("错误", "请输入服务器IP地址!")
return
try:
nickname = simpledialog.askstring("昵称", "请输入你的昵称:")
if nickname:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((server_ip, 58588))
receive_thread = threading.Thread(target=receive)
receive_thread.start()
connect_button.config(state=tk.DISABLED)
ip_entry.config(state=tk.DISABLED)
except:
messagebox.showerror("错误", "无法连接到服务器!")
# 更新在线用户列表
def update_user_list():
user_listbox.delete(0, tk.END)
for user in online_users:
user_listbox.insert(tk.END, user)
# 创建主窗口
root = tk.Tk()
root.title("客户端")
# 左侧框架,包含服务器IP输入框和连接按钮
left_frame = tk.Frame(root)
left_frame.pack(side=tk.LEFT, padx=10, pady=10)
ip_label = tk.Label(left_frame, text="服务器IP:")
ip_label.pack(pady=5)
ip_entry = tk.Entry(left_frame)
ip_entry.pack(pady=5)
connect_button = tk.Button(left_frame, text="连接", command=connect)
connect_button.pack(pady=10)
# 中间框架,包含聊天框
middle_frame = tk.Frame(root)
middle_frame.pack(side=tk.LEFT, padx=10, pady=10)
chat_box = scrolledtext.ScrolledText(middle_frame, width=40, height=20)
chat_box.pack(padx=10, pady=10)
input_box = tk.Entry(middle_frame, width=30)
input_box.pack(pady=10)
input_box.bind("<Return>", send_message)
send_button = tk.Button(middle_frame, text="发送", command=send_message)
send_button.pack(pady=10)
# 右侧框架,包含在线用户列表
right_frame = tk.Frame(root)
right_frame.pack(side=tk.LEFT, padx=10, pady=10)
user_list_label = tk.Label(right_frame, text="在线用户列表")
user_list_label.pack(pady=5)
user_listbox = tk.Listbox(right_frame, width=20, height=20)
user_listbox.pack(padx=10, pady=10)
# 运行主循环
root.mainloop() |