实现了聊天功能
This commit is contained in:
126
client1.py
126
client1.py
@@ -1,59 +1,79 @@
|
||||
import json
|
||||
import socket
|
||||
import threading
|
||||
import json
|
||||
|
||||
def listen_for_messages(sock):
|
||||
"""后台线程:监听并显示消息"""
|
||||
while True:
|
||||
try:
|
||||
data = sock.recv(1024).decode("utf-8")
|
||||
if not data:
|
||||
break
|
||||
resp = json.loads(data)
|
||||
if resp["status"] == "msg":
|
||||
print(f"\n📩 {resp['from']} 发来消息: {resp['msg']}")
|
||||
print("请输入消息(q退出): ", end="", flush=True)
|
||||
elif resp["status"] == "system":
|
||||
print(f"\n👥 在线用户更新: {resp['users']}")
|
||||
print("请输入消息(q退出): ", end="", flush=True)
|
||||
except:
|
||||
break
|
||||
|
||||
def chat(username, chat_obj, content):
|
||||
'''
|
||||
发送聊天信息
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
# 创建socket
|
||||
ip_port = ("127.0.0.1", 9000)
|
||||
sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
|
||||
# 选择菜单
|
||||
while 1:
|
||||
print("menu".center(30, "="))
|
||||
print("1.login".center(30, " "))
|
||||
print("2.register".center(30, " "))
|
||||
print("=".center(30, "="))
|
||||
choice = input(">>>")
|
||||
|
||||
if choice == "1":
|
||||
username = input("用户名:")
|
||||
password = input("密码:")
|
||||
data = {
|
||||
"option": "login",
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
sk.sendto(json.dumps(data).encode("utf-8"), ip_port)
|
||||
msg, addr = sk.recvfrom(1024)
|
||||
# {"status": 1}
|
||||
if json.loads(msg.decode("utf-8"))["status"]:
|
||||
chat_obj = input("输入收件人:")
|
||||
content = input("输入内容:")
|
||||
chat(username, chat_obj, content)
|
||||
continue
|
||||
def login_or_register(sock):
|
||||
while True:
|
||||
print("1. 登录")
|
||||
print("2. 注册")
|
||||
choice = input("请选择: ")
|
||||
username = input("用户名: ")
|
||||
password = input("密码: ")
|
||||
if choice == "1":
|
||||
sock.send(json.dumps({"action": "login", "username": username, "password": password}).encode("utf-8"))
|
||||
else:
|
||||
print("登录失败")
|
||||
sock.send(json.dumps({"action": "register", "username": username, "password": password}).encode("utf-8"))
|
||||
resp = json.loads(sock.recv(1024).decode("utf-8"))
|
||||
print(resp["msg"])
|
||||
if resp["status"] == "ok" and choice == "1":
|
||||
return username
|
||||
|
||||
def chat(sock, username):
|
||||
while True:
|
||||
# 请求在线用户
|
||||
sock.send(json.dumps({"action": "list_users"}).encode("utf-8"))
|
||||
resp = json.loads(sock.recv(1024).decode("utf-8"))
|
||||
users = resp.get("users", [])
|
||||
if not users:
|
||||
print("⚠️ 暂无其他在线用户")
|
||||
continue
|
||||
elif choice == "2":
|
||||
username = input("用户名:")
|
||||
password = input("密码:")
|
||||
data = {
|
||||
"option": "register",
|
||||
"username": username,
|
||||
"password": password
|
||||
}
|
||||
sk.sendto(json.dumps(data).encode("utf-8"), ip_port)
|
||||
msg, addr = sk.recvfrom(1024)
|
||||
# {"status": 1}
|
||||
if json.loads(msg.decode("utf-8"))["status"]:
|
||||
print("注册成功")
|
||||
continue
|
||||
else:
|
||||
print(json.loads(msg.decode("utf-8"))["msg"])
|
||||
print("\n=== 在线用户 ===")
|
||||
for i, u in enumerate(users):
|
||||
print(f"{i+1}. {u}")
|
||||
choice = input("选择聊天对象编号(q退出): ")
|
||||
if choice.lower() == "q":
|
||||
break
|
||||
try:
|
||||
target = users[int(choice)-1]
|
||||
except:
|
||||
print("无效选择")
|
||||
continue
|
||||
|
||||
# 聊天循环
|
||||
while True:
|
||||
msg = input("请输入消息(q退出): ")
|
||||
if msg.lower() == "q":
|
||||
break
|
||||
sock.send(json.dumps({"action": "send", "to": target, "msg": msg}).encode("utf-8"))
|
||||
|
||||
def main():
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect(("127.0.0.1", 8888))
|
||||
|
||||
username = login_or_register(sock)
|
||||
|
||||
# 开启监听线程
|
||||
threading.Thread(target=listen_for_messages, args=(sock,), daemon=True).start()
|
||||
|
||||
# 主线程执行聊天逻辑
|
||||
chat(sock, username)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
80
client2.py
80
client2.py
@@ -1 +1,79 @@
|
||||
import socket
|
||||
import socket
|
||||
import threading
|
||||
import json
|
||||
|
||||
def listen_for_messages(sock):
|
||||
"""后台线程:监听并显示消息"""
|
||||
while True:
|
||||
try:
|
||||
data = sock.recv(1024).decode("utf-8")
|
||||
if not data:
|
||||
break
|
||||
resp = json.loads(data)
|
||||
if resp["status"] == "msg":
|
||||
print(f"\n📩 {resp['from']} 发来消息: {resp['msg']}")
|
||||
print("请输入消息(q退出): ", end="", flush=True)
|
||||
elif resp["status"] == "system":
|
||||
print(f"\n👥 在线用户更新: {resp['users']}")
|
||||
print("请输入消息(q退出): ", end="", flush=True)
|
||||
except:
|
||||
break
|
||||
|
||||
def login_or_register(sock):
|
||||
while True:
|
||||
print("1. 登录")
|
||||
print("2. 注册")
|
||||
choice = input("请选择: ")
|
||||
username = input("用户名: ")
|
||||
password = input("密码: ")
|
||||
if choice == "1":
|
||||
sock.send(json.dumps({"action": "login", "username": username, "password": password}).encode("utf-8"))
|
||||
else:
|
||||
sock.send(json.dumps({"action": "register", "username": username, "password": password}).encode("utf-8"))
|
||||
resp = json.loads(sock.recv(1024).decode("utf-8"))
|
||||
print(resp["msg"])
|
||||
if resp["status"] == "ok" and choice == "1":
|
||||
return username
|
||||
|
||||
def chat(sock, username):
|
||||
while True:
|
||||
# 请求在线用户
|
||||
sock.send(json.dumps({"action": "list_users"}).encode("utf-8"))
|
||||
resp = json.loads(sock.recv(1024).decode("utf-8"))
|
||||
users = resp.get("users", [])
|
||||
if not users:
|
||||
print("⚠️ 暂无其他在线用户")
|
||||
continue
|
||||
print("\n=== 在线用户 ===")
|
||||
for i, u in enumerate(users):
|
||||
print(f"{i+1}. {u}")
|
||||
choice = input("选择聊天对象编号(q退出): ")
|
||||
if choice.lower() == "q":
|
||||
break
|
||||
try:
|
||||
target = users[int(choice)-1]
|
||||
except:
|
||||
print("无效选择")
|
||||
continue
|
||||
|
||||
# 聊天循环
|
||||
while True:
|
||||
msg = input("请输入消息(q退出): ")
|
||||
if msg.lower() == "q":
|
||||
break
|
||||
sock.send(json.dumps({"action": "send", "to": target, "msg": msg}).encode("utf-8"))
|
||||
|
||||
def main():
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect(("127.0.0.1", 8888))
|
||||
|
||||
username = login_or_register(sock)
|
||||
|
||||
# 开启监听线程
|
||||
threading.Thread(target=listen_for_messages, args=(sock,), daemon=True).start()
|
||||
|
||||
# 主线程执行聊天逻辑
|
||||
chat(sock, username)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
134
server.py
134
server.py
@@ -1,41 +1,99 @@
|
||||
import json
|
||||
import socket
|
||||
import threading
|
||||
import json
|
||||
import os
|
||||
|
||||
# 创建socket
|
||||
sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
sk.bind(("0.0.0.0", 9000))
|
||||
active = []
|
||||
db = {}
|
||||
chat_msg = {}
|
||||
DB_FILE = "chat_db.json"
|
||||
ONLINE_USERS = {} # {username: conn}
|
||||
|
||||
while 1:
|
||||
print(f"当前活跃用户:{active} 当前注册用户:{db}")
|
||||
data, addr = sk.recvfrom(2048)
|
||||
data = json.loads(data)
|
||||
res = {"status": 0}
|
||||
if data["option"] == "login":
|
||||
username = data["username"]
|
||||
password = data["password"]
|
||||
if username in db:
|
||||
if db[username] == password:
|
||||
res = {"status": 1}
|
||||
active.append(data["username"])
|
||||
else:
|
||||
res = {"status": 0}
|
||||
else:
|
||||
res = {"status": 0}
|
||||
elif data["option"] == "register":
|
||||
username = data["username"]
|
||||
password = data["password"]
|
||||
if username in db:
|
||||
res = {"status": 0, "msg": "用户名已存在"}
|
||||
else:
|
||||
db[username] = password
|
||||
res = {"status": 1, "msg": "注册成功"}
|
||||
elif data["option"] == "chat":
|
||||
# 接受聊天信息,并且存入聊天临时字典
|
||||
pass
|
||||
elif data["option"] == "hello":
|
||||
# 接受客户端的存活状态,如果发现临时聊天字典有该用户的未收消息,发送过去
|
||||
pass
|
||||
sk.sendto(json.dumps(res).encode("utf-8"), addr)
|
||||
# 初始化数据库
|
||||
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()
|
||||
|
Reference in New Issue
Block a user