WebSocket是html5中实现的一种新协议,相比http优势的是它是一种双向通信协议,不用像通过ajax长轮询请求服务器去实现类似的需求。我们先来看下需要的基础知识:

1、autobahn: autobahn是websocket的python实现。

2、twisted: Twisted是一个python异步解决方案,基于事件驱动的网络引擎框架。


autobahn官方的教程很不错:http://autobahn.ws/python/websocket/programming.html#sending-messages

twisted启动进程的例子:https://twistedmatrix.com/documents/13.0.0/core/howto/process.html


参考国外某大神的例子:https://tomforb.es/displaying-a-processes-output-on-a-web-page-with-websockets-and-python

# 先装包
pip install autobahn twisted

# server程序
[root@node_172_16_214_230 ~]# cat test_run.py
#!/usr/bin/env python

from autobahn.twisted.websocket import WebSocketServerFactory
from autobahn.twisted.websocket import WebSocketServerProtocol
from twisted.internet import reactor, protocol
from twisted.python import msg

COMMAND_NAME = sys.argv[1]
COMMAND_ARGS = sys.argv[1:]

class MyProcessProtocol(protocol.ProcessProtocol):

    def __init__(self, wf):
        self.ws = ws
        self.buffer = []

    def outReceived(self, data):
        self.ws.broadcast(data)
        self.buffer.append(data)
        self.buffer = self.buffer[-10:]

    def errReceived(self, data):
        print "Error: %s" % data


class MyServerProtocol(WebSocketServerProtocol):

   def onConnect(self, request):
       print("Client connecting: {0}".format(request.peer))

   def onOpen(self):
      self.factory.register(self)
      for line in self.factory.process.buffer:
          self.sendMessage(line)

   def connectionLost(self, reason):
      print("WebSocket connection lost: {0}".format(reason))
      self.factory.unregister(self)      
   

class MyWebSocketServerFactory(WebSocketServerFactory):

   def __init__(self, *args, **kwargs):
      super(MyWebSocketServerFactory, self).__init__(*args, **kwargs)
      self.clients = []
      self.process = MyProcessProtocol(self)
      reactor.spawnProcess(self.process,COMMAND_NAME, COMMAND_ARGS, {}, usePTY=True)

   def register(self, client):
      msg("Registered client %s" % client)
      if client not in self.clients:
         self.clients.append(client)

   def unregister(self, client):
      msg("Unregistered client %s" % client)
      if client in self.clients:
         self.clients.remove(client)

   def broadcast(self, message):
      for client in self.clients:
         client.sendMessage(message)


if __name__ == '__main__':
   import sys

   from twisted.python import log
   log.startLogging(sys.stdout)

   factory = MyWebSocketServerFactory("ws://0.0.0.0:9000")
   factory.protocol = MyServerProtocol

   reactor.listenTCP(9000, factory)
   reactor.run()
   
   
# 客户端就是浏览器了
[root@node_172_16_214_230 ~]# cat /var/www/html/index.html

   
      
      
         window.onload = function() {
            window.webSocket = new WebSocket("ws://172.16.214.230:9000");
            window.webSocket.onmessage = function(e) {
               console.log("Got echo: " + e.data);
                $("#output").append(e.data);
            }
         }
      
   
   
      

Ping output:

             
    # 测试 # 启动server端 [root@node_172_16_214_230 ~]# python runner.py tail -f /var/log/httpd/access_log 2016-10-24 15:24:29+0000 [-] Log opened. 2016-10-24 15:24:29+0000 [-] Running process tail with args ['tail', '-f', '/var/log/httpd/access_log'] 2016-10-24 15:24:29+0000 [-] WebSocketProcessOutputterThingFactory starting on 9000 2016-10-24 15:24:29+0000 [-] Starting factory <__main__.WebSocketProcessOutputterThingFactory object at 0x2447690> # 客户端测试 登录