如何在应用退出

时间:2018-06-17 12:37:36

标签: python kivy

我开始学习构建server client apps并找到一个很好的example我的最终目标是将文件从服务器传输到客户端并在应用程序上绘制接收到的数据。

我在这里建立了一个示例应用程序。有人可以建议在退出应用程序时如何调用close socket函数吗?

我假设只需要在程序exit上关闭套接字,而不是在每次文件传输后关闭套接字。因此,我把代码放在最后关闭套接字。

我想过在on_stop课程中使用ClientAPP。但由于尚未创建变量,因此从那里引用函数似乎不可能。

我正在遵循其中一个答案提出的建议here

server.py

# -*- coding: utf-8 -*-

import socket
from threading import Thread

class Server(object):
    def __init__(self):
        #Creates socket object
        self.serversocket = socket.socket()

        self.host = 'localhost'
        self.port = 54545

    #If we had used s.bind(('localhost', 80)) or s.bind(('127.0.0.1', 80)) we would still have a �server� socket, but one that was only visible within the same machine. s.bind(('', 80)) specifies that the socket is reachable by any address the machine happens to have.

    def start_server(self):
        self.serversocket.bind(('', self.port))

        self.serversocket.listen(10)

        self.clientsocket, self.addr = self.serversocket.accept()
        print("got a connection from %s" % str(self.addr))

        confirmation = 'Connected'
        self.clientsocket.send(confirmation.encode())

        #start_listening
        Thread(target=self.print_received_client_data).start()

    def print_received_client_data(self):
        while True:
            print('Received from client: %s' % self.clientsocket.recv(1024).decode())        

if __name__=="__main__":
    Server().start_server()

ClientAPP.py

# -*- coding: utf-8 -*-

from kivy.app import App
from kivy.uix.label import Label
from threading import Thread
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
import socket, time
from kivy.uix.screenmanager import Screen, ScreenManager

class ScreenManagement(ScreenManager):
    pass

class HomeScreen(Screen):
    def __init__(self, **kwargs):
        super(HomeScreen,self).__init__(**kwargs)

        self.sock_instance = MySocket()
        Thread(target=self.set_text_input).start()

    host = "localhost"
    port = 7000
    display = ObjectProperty()

    def set_text_input(self):
        while True:
            time.sleep(0.1)
            self.text = self.sock_instance.get_data()                  

    def send_message(self):  
        #self.ids.display.text is encoded and sent            
        self.sock_instance.sock.send(self.ids.display.text.encode()) 

    def receive_message(self):
        # Decodes a reply, Converts it to a str, prints it           
        print("Message from server - %s" % str(self.sock_instance.sock.recv(1024).decode("ascii")))

class SettingsScreen(Screen):
    pass

class MySocket:

    def __init__(self, host="localhost", port=54545):

        self.sock = socket.socket()
        self.sock.connect((host, port))

        #Receives confirmation from Server, Converts to string, Prints confirmation
        print("%s" % str(self.sock.recv(1024).decode()))         

    def get_data(self):
        return self.sock.recv(1024)

    def close_socket(self):
        self.sock.close()

class ClientAPP(App):

    def build(self):
        runtime_instance = ScreenManagement()
        return runtime_instance

if __name__ == '__main__':
    app_instance = ClientAPP()
    try:
        app_instance.run()
    finally:
        #Code to close socket here, ideally, call close_socket
        print("Closed the socket")

ClientAPP.kv

#: import FadeTransition kivy.uix.screenmanager.FadeTransition

<ScreenManagement>:
    transition:FadeTransition()
    HomeScreen:
    SettingsScreen:

<HomeScreen>:
    RelativeLayout:
        Button:
            size_hint: 0.2,0.2
            pos_hint:{"x":0,"y":0.4}
            text: "Send Message"
            on_press: root.send_message()
        TextInput:
            id: display
            size_hint: 0.2,0.2
            pos_hint:{"x":0.2,"y":0.4}
            text: "abc"

编辑 - 之前发布的server.py不正确

1 个答案:

答案 0 :(得分:0)

解决方案

关闭套接字 - 当窗口关闭时,即单击X

  1. 添加导入语句Window.bind(on_request_close=self.close_socket)
  2. __init__()添加到课程MySocket:的{​​{1}}方法中。
  3. 关闭套接字 - 退出应用

    1. 在kv文件中,添加id: home_screen
    2. 在Python文件中,将on_stop()事件和调用close_socket()方法添加到课程ServerApp()ClientApp()中。
    3. kv文件 - 添加 id

      server.kv&amp; client.kv

      <ScreenManagement>:
          HomeScreen:
              id: home_screen
              name: 'home_screen'
          SettingsScreen:
              name: 'settings_screen'
      

      Python文件

      server.py

      class MySocket:
      
          def __init__(self, host="localhost", port=54545):
              Window.bind(on_request_close=self.close_socket)
      
          ...
      
          def close_socket(self, *largs, **kwargs):
              print("\nServerApp.close_socket:")
              print("\tClosed the socket")
              self.sock.close()
      
      
      class ServerApp(App):
      
          def build(self):
              self.runtime_instance = ScreenManagement()
              return self.runtime_instance
      
          def on_stop(self):
              print('\nServerApp.on_stop:')
              self.runtime_instance.ids.home_screen.sock_instance.close_socket()
      
      
      if __name__ == '__main__':
          ServerApp().run()
      

      main.py

      class MySocket:
      
          def __init__(self, host="localhost", port=54545):
              Window.bind(on_request_close=self.close_socket)
      
          ...
      
          def close_socket(self, *largs, **kwargs):
              print("\nClientApp.close_socket:")
              print("\tClosed the socket")
              self.sock.close()
      
      class ClientApp(App):
      
          def build(self):
              self.runtime_instance = ScreenManagement()
              return self.runtime_instance
      
          def on_stop(self):
              print('\nClientApp.on_stop:')
              self.runtime_instance.ids.home_screen.sock_instance.close_socket()
      
      
      if __name__ == '__main__':
          ClientApp().run()
      

      输出

      ServerApp发送数据

      Img01 - ServerApp send data

      ClientApp收到数据

      Img02 - ClientApp received data

      ServerApp退出

      Img02 - ServerApp exit