100 lines
3.4 KiB
Python
100 lines
3.4 KiB
Python
import socket
|
|
import threading
|
|
import json
|
|
import os
|
|
|
|
DB_FILE = "chat_db.json"
|
|
ONLINE_USERS = {} # {username: conn}
|
|
|
|
# 初始化数据库
|
|
if not os.path.exists(DB_FILE):
|
|
with open(DB_FILE, "w") as f:
|
|
json.dump({"users": {}, "messages": []}, f)
|
|
|
|
def load_db():
|
|
with open(DB_FILE, "r") as f:
|
|
return json.load(f)
|
|
|
|
def save_db(data):
|
|
with open(DB_FILE, "w") as f:
|
|
json.dump(data, f, indent=2, ensure_ascii=False)
|
|
|
|
def handle_client(conn, addr):
|
|
username = None
|
|
try:
|
|
while True:
|
|
data = conn.recv(1024).decode("utf-8")
|
|
if not data:
|
|
break
|
|
req = json.loads(data)
|
|
action = req.get("action")
|
|
|
|
if action == "register":
|
|
db = load_db()
|
|
users = db["users"]
|
|
if req["username"] in users:
|
|
conn.send(json.dumps({"status": "fail", "msg": "用户已存在"}).encode("utf-8"))
|
|
else:
|
|
users[req["username"]] = req["password"]
|
|
save_db(db)
|
|
conn.send(json.dumps({"status": "ok", "msg": "注册成功"}).encode("utf-8"))
|
|
|
|
elif action == "login":
|
|
db = load_db()
|
|
users = db["users"]
|
|
if users.get(req["username"]) == req["password"]:
|
|
username = req["username"]
|
|
ONLINE_USERS[username] = conn
|
|
conn.send(json.dumps({"status": "ok", "msg": "登录成功"}).encode("utf-8"))
|
|
broadcast_users()
|
|
else:
|
|
conn.send(json.dumps({"status": "fail", "msg": "用户名或密码错误"}).encode("utf-8"))
|
|
|
|
elif action == "list_users":
|
|
users = list(ONLINE_USERS.keys())
|
|
if username in users:
|
|
users.remove(username) # 移除自己
|
|
conn.send(json.dumps({"status": "ok", "users": users}).encode("utf-8"))
|
|
|
|
elif action == "send":
|
|
to_user = req["to"]
|
|
msg = req["msg"]
|
|
db = load_db()
|
|
db["messages"].append({"from": username, "to": to_user, "msg": msg})
|
|
save_db(db)
|
|
if to_user in ONLINE_USERS:
|
|
ONLINE_USERS[to_user].send(
|
|
json.dumps({"status": "msg", "from": username, "msg": msg}).encode("utf-8")
|
|
)
|
|
else:
|
|
conn.send(json.dumps({"status": "fail", "msg": "对方不在线"}).encode("utf-8"))
|
|
|
|
except Exception as e:
|
|
print(f"错误: {e}")
|
|
finally:
|
|
if username and username in ONLINE_USERS:
|
|
del ONLINE_USERS[username]
|
|
broadcast_users()
|
|
conn.close()
|
|
|
|
def broadcast_users():
|
|
users = list(ONLINE_USERS.keys())
|
|
for user, conn in ONLINE_USERS.items():
|
|
ulist = [u for u in users if u != user]
|
|
try:
|
|
conn.send(json.dumps({"status": "system", "users": ulist}).encode("utf-8"))
|
|
except:
|
|
pass
|
|
|
|
def main():
|
|
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
server.bind(("0.0.0.0", 8888))
|
|
server.listen(5)
|
|
print("服务器已启动,监听 8888 端口...")
|
|
while True:
|
|
conn, addr = server.accept()
|
|
threading.Thread(target=handle_client, args=(conn, addr), daemon=True).start()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|