我开始学习构建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不正确
答案 0 :(得分:0)
Window.bind(on_request_close=self.close_socket)
__init__()
添加到课程MySocket:
的{{1}}方法中。id: home_screen
on_stop()
事件和调用close_socket()
方法添加到课程ServerApp()
和ClientApp()
中。<ScreenManagement>:
HomeScreen:
id: home_screen
name: 'home_screen'
SettingsScreen:
name: 'settings_screen'
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()
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()