chatserver/chatserver3.0.py
DZY 04373736da feat(py)
新聊天程序

Closes #1
2025-05-31 19:01:43 +08:00

189 lines
7.4 KiB
Python

import socket
import threading
import json
import sqlite3
from datetime import datetime
class ChatServer:
def __init__(self, host='0.0.0.0', port=5555):
self.host = host
self.port = port
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((host, port))
self.server.listen()
self.clients = {}
self.groups = {'General': set()}
self.setup_database()
def setup_database(self):
self.db = sqlite3.connect('chat_server.db', check_same_thread=False)
cursor = self.db.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE,
password TEXT
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sender TEXT,
receiver TEXT,
message TEXT,
timestamp DATETIME,
is_group INTEGER
)
''')
self.db.commit()
def handle_client(self, client, address):
username = None
try:
while True:
message = client.recv(1024).decode('utf-8')
if not message:
break
data = json.loads(message)
if data['type'] == 'login':
username = data['username']
password = data['password']
if self.authenticate_user(username, password):
self.clients[username] = client
self.groups['General'].add(username)
client.send(json.dumps({'type': 'login_success'}).encode('utf-8'))
self.send_user_list()
self.send_group_list(username)
self.send_initial_messages(username)
else:
client.send(json.dumps({'type': 'login_fail'}).encode('utf-8'))
elif data['type'] == 'register':
username = data['username']
password = data['password']
if self.register_user(username, password):
client.send(json.dumps({'type': 'register_success'}).encode('utf-8'))
else:
client.send(json.dumps({'type': 'register_fail'}).encode('utf-8'))
elif data['type'] == 'message':
sender = data['sender']
receiver = data['receiver']
msg = data['message']
is_group = data['is_group']
self.save_message(sender, receiver, msg, is_group)
if is_group:
for member in self.groups.get(receiver, set()):
if member in self.clients and member != sender:
self.clients[member].send(json.dumps({
'type': 'message',
'sender': sender,
'receiver': receiver,
'message': msg,
'is_group': True
}).encode('utf-8'))
else:
if receiver in self.clients:
self.clients[receiver].send(json.dumps({
'type': 'message',
'sender': sender,
'receiver': receiver,
'message': msg,
'is_group': False
}).encode('utf-8'))
elif data['type'] == 'create_group':
group_name = data['group_name']
if group_name not in self.groups:
self.groups[group_name] = set()
for user in data['members']:
if user in self.clients:
self.groups[group_name].add(user)
self.send_group_list_to_all()
except Exception as e:
print(f"Error handling client: {e}")
finally:
if username and username in self.clients:
del self.clients[username]
for group in self.groups.values():
if username in group:
group.remove(username)
self.send_user_list()
client.close()
def authenticate_user(self, username, password):
cursor = self.db.cursor()
cursor.execute('SELECT * FROM users WHERE username=? AND password=?', (username, password))
return cursor.fetchone() is not None
def register_user(self, username, password):
try:
cursor = self.db.cursor()
cursor.execute('INSERT INTO users (username, password) VALUES (?, ?)', (username, password))
self.db.commit()
return True
except sqlite3.IntegrityError:
return False
def save_message(self, sender, receiver, message, is_group):
cursor = self.db.cursor()
cursor.execute('''
INSERT INTO messages (sender, receiver, message, timestamp, is_group)
VALUES (?, ?, ?, ?, ?)
''', (sender, receiver, message, datetime.now(), 1 if is_group else 0))
self.db.commit()
def send_user_list(self):
user_list = list(self.clients.keys())
for client in self.clients.values():
client.send(json.dumps({
'type': 'user_list',
'users': user_list
}).encode('utf-8'))
def send_group_list(self, username):
group_list = [group for group, members in self.groups.items() if username in members]
if username in self.clients:
self.clients[username].send(json.dumps({
'type': 'group_list',
'groups': group_list
}).encode('utf-8'))
def send_group_list_to_all(self):
for username in self.clients:
self.send_group_list(username)
def send_initial_messages(self, username):
cursor = self.db.cursor()
cursor.execute('''
SELECT sender, receiver, message, timestamp, is_group FROM messages
WHERE receiver=? OR (is_group=1 AND receiver IN (
SELECT group_name FROM groups WHERE member=?
)) OR sender=?
ORDER BY timestamp
''', (username, username, username))
messages = []
for sender, receiver, message, timestamp, is_group in cursor.fetchall():
messages.append({
'sender': sender,
'receiver': receiver,
'message': message,
'timestamp': timestamp,
'is_group': is_group
})
if username in self.clients:
self.clients[username].send(json.dumps({
'type': 'initial_messages',
'messages': messages
}).encode('utf-8'))
def start(self):
print(f"Server started on {self.host}:{self.port}")
while True:
client, address = self.server.accept()
thread = threading.Thread(target=self.handle_client, args=(client, address))
thread.start()
if __name__ == "__main__":
server = ChatServer()
server.start()