上一期,用pyqt5 写了用户登录及注册界面: 这里我们主要分以下2个模块: 其他的文件分析: 本次客户端相比于上期内容基本上没有多大变化,只是在上期基础上引入了负责与服务端通讯的client.py文件,修改了do_login用户登录方法及注册界面的register_func用户注册方法。 与服务端通讯: 这里使用TCP套接字来进行通讯。 setting 文件作为客户端通讯地址文件,方便后期客户端在其他地址登录时修改。 以下为setting.txt文件内容: 客户端通讯模块的引入: 解析: 用户名及密码匹配成功,返回 ’OK‘,客户端接收到’OK‘则提示登录成功,并执行相应的其他业务逻辑。 注意: 将创建的通讯对象,传递给注册页面: 使注册页面可以和服务器进行通讯。 解析: 解析: 根据请求头的不同,服务端执行相应的代码,这里我们处理登录和注册的函数放在function.py文件中: 登录方法: 解析: 主要注意信息的处理方式,客户端在构造登录请求的数据时,请求头与请求数据用‘@’连接,用户名与密码之间用‘?’连接,所以这里也用相应的方式分割数据。 注册方法: 数据处理方面的逻辑也和登录方法类似,代码也比较简单,应该不需要解释啥。 本次主要建立起了简单的通讯框架,下一篇应该主要会是登录后聊天界面的创建。 这次模块多了一点,全部源码贴上来意义也不大。还是那句话,要源码的可以私信。 以上内容为原创,未经允许,禁止转载!!用Python做一款带用户界面本地通讯桌面软件 (二:简单网络通讯模型)
前言
用Python做一款带用户界面本地通讯桌面软件 (一:用户登录与注册)
并且用本地文件操作,模拟了用户登录和注册的业务逻辑,本期主要介绍将用户登录和注册加上网络通信模块。1、模块分析
1、客户端 Client 模块:主要存放用户操作界面代码,负责用户操作,接收服务端返回数据,呈现给客户。
2、服务端 Service 模块:主要存放服务端代码,负责接收处理客户请求,并返回数据给客户端。
Client 模块下的temp文件夹:保存用户基本的资料数据,如聊天记录等。
data 文件夹:因没用数据库,所以data文件夹可以看做是服务端数据保存路径。
image文件夹:保存客户端界面用到的图片。
2、客户端功能及代码:
2.1 client.py
''' 客户端通讯 ''' from socket import * # 获取服务器地址: with open('setting.txt','r') as f: data = f.readlines() address = (data[0].strip(),int(data[1])) class Client(object): def __init__(self): # 创建套接字对象 self.sock_fd = socket(AF_INET,SOCK_STREAM) # 连接服务器 self.sock_fd.connect(address) # 发送请求,并接收服务端返回数据 def send_receive(self,message): self.sock_fd.send(message.encode()) data = self.sock_fd.recv(2048) return data.decode()
# 获取服务器地址: with open('setting.txt','r') as f: data = f.readlines() address = (data[0].strip(),int(data[1]))
127.0.0.1 8888
from client import Client # 用户登录页面 class LoginPage(QWidget): '''用户注册,登录窗口''' # 创建客户端以进行连接 try: client = Client() except: pass
2.2 LoginPage类中do_login方法改写
# 登录方法 # 在登录方法中,检查用户设置的登录状态 def do_login(self): # 获取用户输入的用户名及密码 name,password = self.name_line.text(),self.password_line.text() # 向服务端发送登录请求 method = 'LG' # 构建消息内容 message = '%s@%s?%s' % (method,name,password) # 发送消息,并获得返回数据 try: response = self.client.send_receive(message) except: QMessageBox.warning(self,'警告','服务器启动失败!') return # 根据服务器返回信号,处理登录逻辑 if response == 'OK': self.check_login_state() QMessageBox.information(self, '提示', '登录成功!') elif response == 'None': QMessageBox.warning(self, '警告', '暂无用户数据!请先注册!') elif response == 'NME': QMessageBox.warning(self, '警告', '用户不存在!') elif response == 'PDE': QMessageBox.warning(self, '警告', '密码错误!')
自定义登录请求头为’LG‘并与登录请求的数据(用户名,密码)用’@‘连接发送给服务端,服务端接收到信息,根据请求头的不同处理相应请求。
返回 ’None‘ 说明暂无用户数据,客户端发出警告提示框。提示:‘暂无用户数据!请先注册!’。
其他逻辑类似。
客户端与服务器可能会连接失败,如:服务端没有启动,所以发送请求的时候加了个try,except语句。 try: response = self.client.send_receive(message) except: QMessageBox.warning(self,'警告','服务器启动失败!') return
2.3 LoginPage类中do_register方法的改写
# 用户注册方法 def do_register(self): # 调用注册界面 register_page = RegisterPage(self.client) # 注册页面的注册成功信号绑定,在登录页面输入注册成功后的用户ID及密码 register_page.successful_signal.connect(self.successful_func) register_page.exec()
2.3 RegisterPage类中register_func的改写
# 用户注册方法 def register_func(self): # 注册界面数据 # 用户性别数据 gender = self.gender_data() # 注意将性别的整数类型,转化为字符串类型 rt_data = [self.name_line.text(), self.password1_line.text(), self.nick_line.text(),str(gender)] # 构造发送注册请求数据 method = 'RT' data = '?'.join(rt_data) message = '%s@%s' % (method,data) response = self.client.send_receive(message) # 根据服务器返回信号,处理注册逻辑 if response == 'NME': QMessageBox.information(self, '提示', '该用户ID已被注册!') elif response == 'OK': choice = QMessageBox.information(self, '提示', '注册成功,是否登录?',QMessageBox.Yes | QMessageBox.No) # 如选择是,关闭注册页面,并在登录页面用户ID显示注册ID,密码 if choice == QMessageBox.Yes: self.successful_signal.emit([self.name_line.text(), self.password1_line.text()]) self.close() # 如选择否,直接关闭注册页面。 else: self.close()
注册请求的请求头为 ‘RT’,将请求头与注册的数据发送给服务器。让服务器完成注册的业务,并返回相应的信息。3、服务端功能及代码
3.1 服务端主要代码:
''' 本地通讯服务端 ''' from socket import * from multiprocessing import Process import sys # 导入处理客户端简单请求自定义模块 from function import SimpleFun server_ip = '0.0.0.0' server_port = 8888 server_ar = (server_ip,server_port) # 创建服务器类 class Service(object): simple = SimpleFun() def __init__(self): # 创建套接字,流式套接字 self.sock_fd = socket(AF_INET, SOCK_STREAM) self.sock_fd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 绑定服务器地址 self.sock_fd.bind(server_ar) # 启动服务器方法,创建多进程来处理多个客户端的连接 def service_forever(self): print('服务器已启动!') # 设置监听数 self.sock_fd.listen(10) while True: try: # 连接对象,连接对象的IP地址 con, ar = self.sock_fd.accept() print('连接对象IP:', ar) except: continue # 创建进程 handle_client = Process(target=self.handle_client, args=(con,)) # 启动进程 handle_client.start() # 与客户端交互方法 def handle_client(self,con): while True: # 接收客户端消息 message = con.recv(2048) # 处理客户端异常关闭 if not message: break # 解析消息 request = message.decode().split('@') # 拆分消息请求方法,数据 method, data = request[0],request[1] # 处理请求,并返回数据 response = self.hand_request(method,data) # 向客户端返回数据 con.send(response.encode()) # 处理异常关闭 con.close() sys.exit() # 处理客户端请求方法 def hand_request(self,method,data): # 处理登录请求 if method == 'LG': # 调用登录方法 response = self.simple.login(data) return response # 处理注册请求 elif method == 'RT': # 调用注册方法 response = self.simple.register(data) return response # 启动客户端 if __name__ == '__main__': S = Service() S.service_forever()
1、先创建套接字。
2、创建服务器启动方法: service_forever
这里用了多进程来处理客户端信息,用了Python的Process模块。不了解的同学可以自己网上搜索下资料简单的了解一下,这里用的也很简单。
3、服务端处理登录请求,注册请求方法: # 处理客户端请求方法 def hand_request(self,method,data): # 处理登录请求 if method == 'LG': # 调用登录方法 response = self.simple.login(data) return response # 处理注册请求 elif method == 'RT': # 调用注册方法 response = self.simple.register(data) return response
# 导入处理客户端简单请求自定义模块 from function import SimpleFun
3.2 服务端的登录方法及注册方法
''' 处理客户端简单请求方法 ''' import pickle class SimpleFun(object): def __init__(self): pass # 处理登录请求 def login(self,data): # 拆分接收到的数据 name,password = data.split('?') try: # 用Python自带模块pickle来进行文件读取操作,以rb方式读取文件 with open('./data/users.pkl', 'rb') as f: users = pickle.load(f) except: # 无注册数据返回值 return 'None' if name in users.keys(): if password == users[name][0]: # 登录成功返回值 return 'OK' else: # 密码错误返回值 password error return 'PDE' else: # 用户名错误返回值 name error return 'NME'
根据客户端发送过来的数据,来执行相应的数据判断。 # 拆分接收到的数据 name,password = data.split('?')
# 处理注册请求 def register(self,data): ID = data.split('?')[0] try: with open('./data/users.pkl', 'rb') as f1: users = pickle.load(f1) except: users = {} # 如果用户ID已存在,提示用户ID已被注册 if ID in users.keys(): # 返回用户ID已存在信号 return 'NME' # 否则收集用户注册信息 else: user_data = data.split('?')[1:] users[ID] = user_data with open('./data/users.pkl', 'wb') as f2: pickle.dump(users, f2) # 返回注册成功信号 return 'OK'
4 下篇预告
5 最后
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算