在Python3中使用telnet服务器中的websockets

时间:2014-07-21 00:15:59

标签: python sockets websocket

我一直在研究用python3编写的游戏服务器。我的目标是保持其上的通信选项非常开放,以便多个不同的客户端可以轻松连接。目前所有通信都是通过telnet使用miniboa。我想有选择允许基于Web的客户端。似乎最简单的选择是允许websocket连接。我一直在玩websockify,但是如果可能的话我宁愿不使用代理,因为所有的连接似乎来自代理。理想情况下,我想要的是我可以放入我的telnet服务器以识别websocket握手请求(与常规请求相比),返回正确的握手,然后保持连接,以便通过telnet发送/接收命令websockets是一样的。我无法找到允许我自动执行此操作的任何内容,因此我一直在尝试编写自己的代码以识别websocket握手并使用相应的握手进行回复。我查看了许多其他帖子和示例,特别是python websocket handshake (RFC 6455)我修改并转换为以下测试程序

#!/usr/bin/env python3

from miniboa import TelnetServer
from base64 import b64encode
from hashlib import sha1

clientlist = []


def client_connects(client):
    clientlist.append(client)


def client_disconnects(client):
    clientlist.remove(client)

def process_clients():
    for client in clientlist:
        if client.active and client.cmd_ready:
            total_cmd = client.get_command()
            print("incoming = {}" .format(total_cmd))
            if total_cmd.find(" ") != -1: # breaking apart incoming command
                cmd, cmd_var = total_cmd.split(" ", 1)
            else:
                cmd = total_cmd
                cmd_var = ""
            if cmd == "Sec-WebSocket-Key:":
                GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
                cmd_var = cmd_var + GUID
                encoded = cmd_var.encode('utf-8')
                response_key = b64encode(sha1(encoded).digest())
                websocket_answer = (
                    'HTTP/1.1 101 Switching Protocols',
                    'Upgrade: websocket',
                    'Connection: Upgrade',
                    'Sec-WebSocket-Accept: {key}\r\n\r\n',
                )
                handshake = '\r\n'.join(websocket_answer).format(key=response_key)
                client.handshakestr = handshake
            if cmd == "Upgrade:":
                print("Sending handshake:")
                print(client.handshakestr)
                print("End of Handshake")
                client.send(client.handshakestr)

server = TelnetServer(port=6112, on_connect=client_connects, on_disconnect=client_disconnects)

while True:
    process_clients()
    server.poll()

这似乎让我经历了最初的握手,但随后它立即下降。从输出看起来浏览器期待进一步的东西,但我无法弄清楚是什么。对于客户端,我在http://opiate.github.io/SimpleWebSocketServer/

下载的firefox 29.0上使用以下代码
<!DOCTYPE html>

<meta charset="utf-8" />

<title>WebSocket Test</title>

<script language="javascript" type="text/javascript">


  function init()
  {
    document.myform.url.value = "ws://localhost:8000/"
    document.myform.inputtext.value = "Hello World!"
    document.myform.disconnectButton.disabled = true;
  }

  function doConnect()
  {
    websocket = new WebSocket(document.myform.url.value);
    websocket.onopen = function(evt) { onOpen(evt) };
    websocket.onclose = function(evt) { onClose(evt) };
    websocket.onmessage = function(evt) { onMessage(evt) };
    websocket.onerror = function(evt) { onError(evt) };
  }

  function onOpen(evt)
  {
    writeToScreen("connected\n");
    document.myform.connectButton.disabled = true;
    document.myform.disconnectButton.disabled = false;
  }

  function onClose(evt)
  {
    writeToScreen("disconnected\n");
    document.myform.connectButton.disabled = false;
    document.myform.disconnectButton.disabled = true;
  }

  function onMessage(evt)
  {
    writeToScreen("response: " + evt.data + '\n');
  }

  function onError(evt)
  {
    writeToScreen('error: ' + evt.data + '\n');

    websocket.close();

    document.myform.connectButton.disabled = false;
    document.myform.disconnectButton.disabled = true;

  }

  function doSend(message)
  {
    writeToScreen("sent: " + message + '\n'); 
    websocket.send(message);
  }

  function writeToScreen(message)
  {
    document.myform.outputtext.value += message
    document.myform.outputtext.scrollTop = document.myform.outputtext.scrollHeight;

  }

  window.addEventListener("load", init, false);


   function sendText() {
        doSend( document.myform.inputtext.value );
   }

  function clearText() {
        document.myform.outputtext.value = "";
   }

   function doDisconnect() {
        websocket.close();
   }


</script>

<div id="output"></div>

<form name="myform">
<p>
<textarea name="outputtext" rows="20" cols="50"></textarea>
</p>
<p>
<textarea name="inputtext" cols="50"></textarea>
</p>
<p>
<textarea name="url" cols="50"></textarea>
</p>
<p>
<input type="button" name=sendButton value="Send" onClick="sendText();">
<input type="button" name=clearButton value="Clear" onClick="clearText();">
<input type="button" name=disconnectButton value="Disconnect" onClick="doDisconnect();">
<input type="button" name=connectButton value="Connect" onClick="doConnect();">
</p>


</form>
</html> 

所以有人都知道: 1.使用我的telnet服务器的websockets更简单的方法? 2.我尝试响应websocket连接有什么问题? 3.如果我放弃并决定使用带有网络连接的代理?

1 个答案:

答案 0 :(得分:0)

Tornado有一个很好的合规WebSocket handler。你可以使用它,或在构建你的时候使用for reference