首页 > 解决方案 > 使用套接字接收数据时 Kivy UI 崩溃 (client.recv())

问题描述

嗨,我正在为我的计算机科学学校项目构建一个网上银行应用程序。

对于应用程序,我使用套接字库将 Kivy 客户端连接到数据库。因此,当我在客户端使用 client.recv() 方法时,应用程序会冻结。

该应用程序有一个登录页面,一旦用户输入登录凭据,用户名和密码就会发送到服务器。服务器使用 python-mysql 连接器验证数据库的凭据,并发送回first_name用户的凭据,显示在菜单页面中。但是由于 kivy 一次构建所有屏幕,即同时创建登录页面和菜单页面。应用程序冻结在client.recv().

有没有其他方法可以在 kivy 中使用套接字接收数据包?

这是问题所在:

    class MenuScreen(Screen):
    data = pickle.loads(client.recv(1024))
    return data

client.py

import time
from _thread import start_new_thread
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.core.window import Window
from kivymd.uix.button import MDRoundFlatIconButton, \
    MDFlatButton, MDRaisedButton
from kivymd.uix.textfield import MDTextField
from kivymd.uix.dialog import MDDialog
from kivy.clock import Clock

import socket, pickle

# SOCKET SETUP

# CONSTANTS
BUFFER = 1024
ADDR = '127.0.0.1'
PORT = 9090

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((ADDR, PORT))

screen_helper = '''
ScreenManager:
    LoginScreen:
    MenuScreen:
    RegisterScreen:
    
<LoginScreen>:
    name: 'login'

    username: username
    password: password

    Image:
        source: 'G:/My Drive/Scripts/Projects/KivyGUI/backgroundLight.jpeg'
        
        canvas:
            Color:
                rgba:(1,1,1,0.7)
                
            Rectangle:
                pos: 500,200
                size: 275,400
    
    MDLabel:
        text: 'Login'
        font_style: 'H2'
        font_size: 50
        theme_text_color: 'Secondary'
        halign: 'center'
        pos_hint: {'center_y': 0.73}        

    MDTextField:
        id: username
        hint_text: 'Username'
        icon_right: "android"
        icon_right_color: app.theme_cls.primary_color
        pos_hint: {'center_x': 0.5, 'center_y': 0.6}
        size_hint_x: None
        width: 250
        
    MDTextField:
        id: password
        hint_text: 'Password'
        helper_text: 'forgot password?'
        helper_text_mode: 'on_focus'
        icon_right: "android"
        icon_right_color: app.theme_cls.primary_color
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}
        size_hint_x: None
        width: 250
        
    MDRectangleFlatButton:
        text: 'Login'
        pos_hint: {'center_x': 0.565, 'center_y': 0.4}
        size_hint_x: None
        width: 250
        on_release:
            root.show_data(None)
            root.manager.current = 'menu'
            
    MDFlatButton:
        text: 'Register'
        theme_text_color: 'Hint'
        pos_hint: {'center_x': 0.43, 'center_y': 0.4}
        size_hint_x: None
        width: 250
        on_release:
            root.manager.current = 'register'

<MenuScreen>:
    name: 'menu'

    Image:
        source: 'G:/My Drive/Scripts/Projects/KivyGUI/backgroundDark.jpeg'        
        
    GridLayout:
        canvas:
            Color:
                rgba:(0,0,0,0.4)

            Rectangle:
                pos: self.pos
                size: self.size
            
        
    GridLayout:
        size_hint: 0.4, 0.6
        pos_hint: {'center_x': 0.65, 'center_y': 0.5}
        spacing: 20
        padding_x: 0.8
        cols: 2
                
        MDRectangleFlatButton:
            text: 'Profile'
            size_hint: 0.4,0.1
            font_size: 25
        MDRectangleFlatButton:
            text: 'Transaction History'
            size_hint: 0.4,0.1
            font_size: 25
        MDRectangleFlatButton:
            text: 'Send Money'
            size_hint: 0.4,0.1
            font_size: 25
        MDRectangleFlatButton:
            text: 'Received Money'
            size_hint: 0.4,0.1
            font_size: 25
    
    FloatLayout:
        orientation: 'tb-lr'
        size_hint: 0.3,1
        pos_hint: {'top': 1, 'left': 0}
        canvas:
            Color:
                rgba:(1,1,1,0.7)

            Rectangle:
                pos: self.pos
                size: self.size
        
        Image:
            source: 'G:/My Drive/Scripts/Projects/KivyGUI/profileIcon2.png'
            pos_hint: {'center_x': 0.5, 'center_y': 0.7}
            size_hint: 0.7,0.7
            
        MDLabel:
            text: 'Welcome back,'
            font_style: 'H4'
            theme_text_color: 'Secondary'
            halign: 'center'
            pos_hint: {'center_y': 0.43}
            
        MDLabel:
            text: ''
            font_style: 'H2'
            font_size: 50
            halign: 'center'
            pos_hint: {'center_y': 0.36}
            
        # MDTextButton:
        #     text: 'Change profile pic'
        #     text_color: (0, 0, 0, 0)
        #     pos_hint: {'center_x': 0.5, 'center_y': 0.5}
            
    GridLayout:
        size_hint: 0.7,0.1
        pos_hint: {'right': 1, 'center_y': 1}
        canvas:
            Color:
                rgba:(1,1,1,0.7)

            Rectangle:
                pos: self.pos
                size: self.size
        
    MDIconButton:
        icon: 'cog'
        pos_hint: {'center_y': 0.975, 'right': 1}

    MDIconButton:
        icon: 'account-off'
        pos_hint: {'center_y': 0.975, 'right': 0.97}
        on_release:
            root.manager.current = 'login'


<RegisterScreen>:
    name: 'register'
    
    firstname: firstname
    lastname: lastname
    r_username: r_username
    r_password: r_password
    email: email
    phone: phone
    
    Image:
        source: 'G:/My Drive/Scripts/Projects/KivyGUI/backgroundLight.jpeg'
    
    GridLayout:
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}
        size_hint: 0.4,0.9
        canvas:
            Color:
                rgba: (1,1,1,0.9)
            
            Rectangle:
                pos: self.pos
                size: self.size
        
    MDLabel:
        text: 'Register'
        font_style: 'H2'
        halign: 'center'
        pos_hint: {'center_y': 0.82}
        color: 0,0,0,0.5
    
    MDTextField:
        id: firstname
        hint_text: 'First Name'
        pos_hint: {'center_x': 0.4, 'center_y': 0.65}
        size_hint_x: None
        width: 200
    
    MDTextField:
        id: lastname
        hint_text: 'Last Name'
        pos_hint: {'center_x': 0.6, 'center_y': 0.65}
        size_hint_x: None
        width: 200
        
    MDTextField:
        id: r_username
        hint_text: 'Username'
        pos_hint: {'center_x': 0.4, 'center_y': 0.5}
        size_hint_x: None
        width: 200
    
    MDTextField:
        id: r_password
        hint_text: 'Password'
        pos_hint: {'center_x': 0.6, 'center_y': 0.5}
        size_hint_x: None
        width: 200
        
    MDTextField:
        id: email
        hint_text: 'Email id'
        pos_hint: {'center_x': 0.4, 'center_y': 0.35}
        size_hint_x: None
        width: 200
    
    MDTextField:
        id: phone
        hint_text: 'Contact no.'
        pos_hint: {'center_x': 0.6, 'center_y': 0.35}
        size_hint_x: None
        width: 200
        
    MDRaisedButton:
        text: 'Next'
        pos_hint: {'center_x': 0.6, 'center_y': 0.2}
        on_release:
            root.manager.current = 'login'
            root.retData(None)

    MDRaisedButton:
        text: 'Back'
        pos_hint: {'center_x': 0.4, 'center_y': 0.2}
        on_release: 
            root.manager.current = 'login'
'''

Window.size = (1280, 720)


class LoginScreen(Screen):
    username = ObjectProperty(None)
    password = ObjectProperty(None)

    def show_data(self, obj):
        print(self.username.text, self.password.text)

        client.send(pickle.dumps(['login', self.username.text, self.password.text]))

class MenuScreen(Screen):
    data = pickle.loads(client.recv(1024))
    return data

class RegisterScreen(Screen):
    firstname = ObjectProperty(None)
    lastname = ObjectProperty(None)
    r_username = ObjectProperty(None)
    r_password = ObjectProperty(None)
    email = ObjectProperty(None)
    phone = ObjectProperty(None)

    def retData(self, obj):
        print(self.r_username.text,
              self.r_password.text,
              self.firstname.text,
              self.lastname.text,
              self.email.text,
              self.phone.text, sep='\n')

        client.send(pickle.dumps(['insertion', self.r_username.text, self.r_password.text,
                                  self.firstname.text, self.lastname.text,
                                  self.email.text, int(self.phone.text)]))


sm = ScreenManager()
sm.add_widget(LoginScreen(name='login'))
sm.add_widget(RegisterScreen(name='register'))


class DemoApp(MDApp):
    def build(self):
        self.theme_cls.primary_palette = 'Pink'
        self.theme_cls.theme_style = 'Light'
        screen = Builder.load_string(screen_helper)
        return screen


DemoApp().run()

server.py

import socket, pickle
from _thread import start_new_thread
import mysql.connector as mys

# SOCKET SETUP

# CONSTANTS
BUFFER = 1024
ADDR = '127.0.0.1'
PORT = 9090

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((ADDR, PORT))
server.listen(5)


def receive(client):
    while True:
        info = pickle.loads(client.recv(1024))
        if info[0] == 'insertion':
            insertion(info)
        if info[0] == 'login':
            display(client, info)


def handle_client():
    print('[ONLINE AND READY!]')
    while True:
        client, addr = server.accept()

        print(addr[0])

        start_new_thread(receive, (client,))


# MySQL Connection
myconn = mys.connect(host='localhost', user='root', port=15000,
                     passwd='adis', database='bank')

mycur = myconn.cursor()

if myconn.is_connected(): print('\n•CONNECTION SUCCESSFUL•')


def insertion(dt):
    try:
        data = f'INSERT INTO users (username, password, firstname, lastname, emailaddress, phonenumber, balance) VALUES("{str(dt[1])}", "{str(dt[2])}", "{str(dt[3])}", "{str(dt[4])}", "{str(dt[5])}", {int(dt[6])}, 1000);'
        print(data)
        mycur.execute(data)

        myconn.commit()

    except Exception as e:
        print(e)


def display(client, info):
    try:
        query = "SELECT username, password FROM users"

        mycur.execute(query)

        rs = mycur.fetchall()  # Record Set

        if tuple(info[1:]) in rs:
            print(tuple(info[1:]))

        client.send(pickle.dumps(info[1]))

    except Exception as e:
        print(e)


handle_client()

请帮帮我,我已经迟到了。

标签: pythonpython-3.xsocketskivyrecv

解决方案


推荐阅读