{"id":8685,"date":"2016-03-27T17:16:40","date_gmt":"2016-03-27T22:16:40","guid":{"rendered":"httpss:\/\/www.powenko.com\/wordpress\/?p=8685"},"modified":"2016-03-27T17:16:40","modified_gmt":"2016-03-27T22:16:40","slug":"%e5%bb%ba%e7%ab%8b%e4%b8%80%e5%80%8budp-%e5%92%8c-%e8%a6%96%e7%aa%97%e7%9a%84python-%e7%a8%8b%e5%bc%8f","status":"publish","type":"post","link":"https:\/\/www.powenko.com\/wordpress\/?p=8685","title":{"rendered":"\u5efa\u7acb\u4e00\u500bUDP \u548c  \u8996\u7a97\u7684Python \u7a0b\u5f0f"},"content":{"rendered":"<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nimport Queue\r\nimport SocketServer\r\nimport socket\r\nimport sys\r\nimport logging\r\nimport threading\r\nimport Tkinter as tk\r\nfrom ScrolledText import ScrolledText\r\n \r\nclass QueueLogger(logging.Handler):\r\n    def __init__(self, queue):\r\n        logging.Handler.__init__(self)\r\n        self.queue = queue\r\n \r\n    # write in the queue\r\n    def emit(self, record):\r\n        self.queue.put(self.format(record).rstrip('\\n') + '\\n')\r\n \r\nclass LoggedUDPServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):\r\n    def __init__(self, server_address, RequestHandlerClass, logger):\r\n        SocketServer.UDPServer.__init__(self, server_address, RequestHandlerClass)\r\n        # Add the queue logger\r\n        self.logger = logger\r\n \r\nclass UDPHandler(SocketServer.BaseRequestHandler):\r\n    def handle(self):\r\n        # Queue logger is un under the self.server object\r\n        self.server.logger.debug(self.request&#x5B;0])\r\n \r\nclass MainApplication:\r\n    def __init__(self, root, log_level, ip, port ):\r\n        self.root = root\r\n        self.log_level = log_level\r\n        self.ip = ip\r\n        self.port = port\r\n        self.root.columnconfigure(0, weight=1)\r\n        self.root.rowconfigure(0, weight=1)\r\n \r\n        # 2 rows: firts with settings, second with registrar data\r\n        self.main_frame = tk.Frame(self.root)\r\n        # Commands row doesn't expands\r\n        self.main_frame.rowconfigure(0, weight=0)\r\n        # Logs row will grow\r\n        self.main_frame.rowconfigure(1, weight=1)\r\n        # Main fram can enlarge\r\n        self.main_frame.columnconfigure(0, weight=1)\r\n        self.main_frame.columnconfigure(1, weight=1)\r\n        self.main_frame.grid(row=0, column=0, sticky=tk.NSEW)\r\n \r\n        # Run\/Stop button\r\n        self.control_button = tk.Button(self.main_frame, text=&quot;Run Server&quot;, command=self.run_server)\r\n        self.control_button.grid(row=0, column=0, sticky=tk.N)\r\n \r\n        # Clear button\r\n        self.clear_button = tk.Button(self.main_frame, text=&quot;Clear Log&quot;, command=self.clear_log)\r\n        self.clear_button.grid(row=0, column=1, sticky=tk.N)\r\n \r\n        # Stop log button\r\n        self.control_log_button = tk.Button(self.main_frame, text=&quot;Pause Log&quot;, command=self.stop_log)\r\n        self.control_log_button.grid(row=0, column=2, sticky=tk.N)\r\n \r\n        # Logs Widget\r\n        self.log_widget = ScrolledText(self.main_frame)\r\n        self.log_widget.grid(row=1, column=0, columnspan=3, sticky=tk.NSEW)\r\n \r\n        # Not editable\r\n        self.log_widget.config(state='disabled')\r\n \r\n        # Queue where the logging handler will write\r\n        self.log_queue = Queue.Queue()\r\n \r\n        # Stup the logger\r\n        l = logging.getLogger('logger')\r\n        l.setLevel(self.log_level)\r\n        formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')\r\n        # Use the QueueLogger as Handler\r\n        hl = QueueLogger(queue=self.log_queue)\r\n        hl.setFormatter(formatter)\r\n        l.addHandler(hl)\r\n        self.logger = logging.getLogger('logger')\r\n \r\n        # Setup the update_widget callback reading logs from the queue\r\n        self.start_log()\r\n \r\n    def stop_log(self):\r\n        self.logger.debug(&quot;Pausing the logger&quot;)\r\n        if self.logger_alarm is not None:\r\n            self.log_widget.after_cancel(self.logger_alarm)\r\n            self.control_log_button.configure(text=&quot;Start Log&quot;, command=self.start_log)\r\n            self.logger_alarm = None\r\n \r\n    def start_log(self):\r\n        self.logger.debug(&quot;Starting the logger&quot;)\r\n        self.update_widget(self.log_widget, self.log_queue)\r\n        self.control_log_button.configure(text=&quot;Pause Log&quot;, command=self.stop_log)\r\n \r\n    def update_widget(self, widget, queue):\r\n        widget.config(state='normal')\r\n        # Read from the Queue and add to the log widger\r\n        while not queue.empty():\r\n            line = queue.get()\r\n            widget.insert(tk.END, line)\r\n            widget.see(tk.END)  # Scroll to the bottom\r\n            widget.update_idletasks()\r\n        widget.config(state='disabled')\r\n        self.logger_alarm = widget.after(10, self.update_widget, widget, queue)\r\n \r\n    def clear_log(self):\r\n        self.log_widget.config(state='normal')\r\n        self.log_widget.delete(0.0, tk.END)\r\n        self.log_widget.config(state='disabled')\r\n \r\n    def run_server(self):\r\n        self.logger.debug(&quot;Starting thread&quot;)\r\n        try:\r\n            self.server = LoggedUDPServer((self.ip, self.port), UDPHandler, self.logger)\r\n            self.server_thread = threading.Thread(name='server', target=self.server.serve_forever)\r\n            self.server_thread.daemon = True\r\n            self.server_thread.start()\r\n            self.control_button.configure(text=&quot;Stop Server&quot;, command=self.stop_server)\r\n        except Exception, e:\r\n            self.logger.error(&quot;Cannot start the server: %s&quot; % e)\r\n            raise e\r\n \r\n    def stop_server(self):\r\n        self.logger.debug(&quot;Stopping server&quot;)\r\n        self.server.shutdown()\r\n        self.server.socket.close()\r\n        self.logger.debug(&quot;Server stopped&quot;)\r\n        self.control_button.configure(text=&quot;Run Server&quot;, command=self.run_server)\r\n \r\nif __name__ == &quot;__main__&quot;:\r\n    root = tk.Tk()\r\n    if len(sys.argv) == 3:\r\n        port = int(sys.argv&#x5B;2])\r\n        address = sys.argv&#x5B;1]\r\n \r\n        app = MainApplication(root, logging.DEBUG, address, port)\r\n        root.title(sys.argv&#x5B;0])\r\n        root.mainloop()\r\n    else:\r\n        print &quot;Error: you must specify address and port..&quot;\r\n        sys.exit(-1)\r\n\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>import Queue import SocketServer import socket import s [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":8686,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[319],"tags":[],"class_list":["post-8685","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ch30-internet"],"_links":{"self":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/8685"}],"collection":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=8685"}],"version-history":[{"count":1,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/8685\/revisions"}],"predecessor-version":[{"id":8687,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/8685\/revisions\/8687"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=\/wp\/v2\/media\/8686"}],"wp:attachment":[{"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=8685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=8685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.powenko.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=8685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}