TCP聊天服务器套接字v1.2
所有版本记录:
v1.0
: TCP聊天服务器套接字|PyQt5+socket(TCP端口映射+端口放行)+logging+Thread(含日志,html)+anaconda打包32位exe(3.4万字)|python高阶
v1.1
: python TCP套接字服务器v1.1-新增服务端命令功能及修改bug(socket+PyQt5)
(v1.2
只改了服务端文件夹)
文章目录
文件目录:
警告[!] :
clients
子目录自动生成, 无需新建.你新建
clients
了也行, 但别建无内容的
data.json
log.txt
日志文件自动生成
|1.用户注册 登录(.json) md5加密密码
data.py
(1).导入
from json import load, dump
from os import path, mkdir
from hashlib import md5
from time import time
(2).md5加密
#from hashlib import md5(上文)
def encode(data:str):
m = md5()
m.update(data.encode('utf8'))
return m.hexdigest()
(3).用户类 json
file = '.\clients\data.json'
folder = '.\clients'
if not path.exists(folder):
mkdir(folder)
class user():
def __init__(self):
if path.exists(file):
with open(file, 'r') as f:
self.data = load(f)
else:
self.data = {
}
def __get__(self, username, default=None) -> tuple:
return self.data.get(username, default)
def __in__(self, username) -> bool:
return username in self.data.keys()
def __write__(self) -> None:
with open(file, 'w') as f:
dump(self.data, f)
def __register__(self, username, password, time:(int, float)) -> None:
self.data[username] = (encode(password), int(time))
self.__write__()
def __login__(self, username, password) -> bool:
return self.data[username][0] == encode(username)
def handler(self, username, password) -> bool:
if self.__in__(username):
return self.__login__(username, password)
else:
self.__register__(username, password, time())
return True
def get_time(self, username):
return self.data[username][1]
server.py
import data
class Client():
...
def login(self):
self._send(f'<font color="red">欢迎来到服务器[{
self.server.address[0]}].您的ip地址为{
self.socket.getpeername()[0]}')
self.username = self.recv()[:8]
if self.server.user_record.__in__(self.username):
self._send("<font color='red'>请输入您的密码: (右下[send]键发送)</font>")
i = self.recv()
if self.server.user_record.handler(self.username, i):
self._send(f'<font color="green">欢迎回来, {
self.username}.</font>')
else:
self._send('<font color="red">密码错误,请重试.</font>')
self.__del__()
else:
def normal(string):
return (4 <= len(string) <= 10) and not ('\n' in string)
while True:
self._send("<font color='blue'>[i]提示: 密码需在4 ~ 10位之间, 且不能换行.</font>\n<font color='red'>请输入您的密码: (右下[send]键发送)</font>")
p1 = self.recv()
if normal(p1):
break
while True:
self._send("<font color='red'>再次输入您的密码: (右下[send]键发送)</font>")
p2 = self.recv()
if p1 == p2:
break
else:
self._send("<font color='red'>密码与前次不符!</font>")
self.server.user_record.handler(self.username, p1)
self._send(f'初来乍到, {
self.username}')
self._login = True
self.server.login(self.username,self.addr)
|2.服务端将用户处理从函数改为类
将用户处理的线程改为Client
类,有助于管理, 处理报错, 并且Server
类可以减少不确定的错误
Client 用户处理类
class Client(object):
class QuitError(Exception):
def __init__(self, *args):
super().__init__(*args)
def __init__(self, socket, addr, server:Server):
self.socket = socket
self.addr = addr
if not isinstance(server, Server):
raise ValueError
self.server = server
self.encode = self.server.encode
self.com = Command_Handler(self)
@self.error
def _recv(self) -> bytes:
return self.socket.recv(bytecount **2).decode(encoding=self.encode).strip()
self._recv = lambda : _recv(self)
@self.error
def _send(self, message=str()) -> None:
self.socket.sendall(message.encode(self.encode))
self._send = lambda m: _send(self, m)
def __del__(self):
self.socket.close()
def isLogin(self) -> bool:
re