First, the theme : Real-time display server-side dynamically generated log files
Second, the process :
1. The client browser establishes a WebSocket link with the server, the server suspends the Save link instance, waits for the new content to trigger the return action
2. Log server scripts loop to discover new content and discover new lines to tornado waiting for API POST to send new content
3. The Tornado processor receives new content and returns a new row via WebSocket to the saved client link
4. The client browser receives new content, retouching, display
Third, the code :
1. Tornado Server URL routing, basic page handler, and HTML:
#模块路径根据自身项目而定 (R '/logs/index/', ' Apps.logs.handler.IndexHandler '), (R '/logs/newlinesforcallbacker/ ', ' Apps.logs.handler.WriteNewLinesHandler '), (R '/logs/newlinesforserver/', ' Apps.logs.handler.ReceiveNewLinesHandler '),
Class Indexhandler (Basehandler): "Home" def get (self, *args, **kwargs): self.render (' logs/index.html ')
<div align= "center" >
2. Server-side WebSocket handler (writenewlineshandler), save delete Link processing class and client WebSocket request JS
class prostatus (object): ' Processing class ' ' W_register = [] def register (self, c Allbacker): "Record Client Connection instance" Self.w_register.append (Callbacker) def unregister (self, callbacker): "Delete Client Connection instance" ' Self.w_register.remove (callbacker) def makelines (self, lines): ' Handle accepted line contents ' Pass Def trigger (self, line): "Send latest content to all logged clients" Passclass Writenewlineshandler (tornado.websocket.We Bsockethandler): "Accept websocket link, save link instance" def check_origin (Self, origin): #针对websocket处理类重写同源检查的方法 re Turn True def open (self): ' Handle new Connection ' ' Prostatus (). Register (self) def on_close (self): Prosta Tus (). Unregister (self) #删除客户端连接 def on_message (self, message): Pass
$ (function () { function Requesttext () { host = "ws://" + Location.hostname + ":" + Location.port + "/LOGS/NEWLINESF orcallbacker/" websocket = new WebSocket (host) Websocket.onopen = function (evt) {} //Establish connection Websocket.onmessage = function (evt) { //Gets the information returned by the server data = $.parsejson (evt.data) $ ("#main"). Append (data+ "</br>") //write page } websocket.onerror = function (evt) {} } Requesttext ()})
3. Tornado wait for the script to submit new content processing handler (Receivenewlineshandler), send new content functions to the pending client, and traverse the log to submit a new content script
class prostatus (object): ' Processing class ' ' W_register = [] def register (self, c Allbacker): "Record Client Connection instance" pass Def unregister (self, callbacker): "Delete Client connection instance" pass def makelines (self, Lines): "Handles accepted line contents" ' for lines in Lines:self.trigger Gger (self, line): "Send latest content to all logged clients" ' for Callabler in Self.w_register:callabler.write_messa GE (json.dumps Line) class Receivenewlineshandler (Basehandler): "Accept server-side script submitted with the latest lines of content '" Def post (self, *args, **kwar GS): Linesdata = self.get_argument (' lines ', ') #print type (json.loads (linesdata)) Prostatus (). Makeli NES (Json.loads (linesdata))
#-*-coding:utf-8-*-author = ' zhouwang ' Import timeimport urllibimport Urllib2import Jsonp = 0while true:f = open (' Logs.txt ', ' r+ ') F.seek (p, 0) #偏移到上次结束位置 lines = F.readlines () If lines: #对行内容操作, send the latest line content to the server data = Urllib.urlencode ({' Lines ': Json.dumps (lines)}) url = ' Http://lo calhost:8800/logs/newlinesforserver/' req = urllib2. Request (URL, data) Res_data = Urllib2.urlopen (req) #print res_data.read () #获取当前位置, as offset value P = F.tell () F.close () time.sleep (1)