1

我正在尝试将 html5 websocket 连接到 python。我有两个文件:

1. index.html

<script>
      window.onload = function() {
        var connection = new WebSocket("ws://localhost:9876/");
        connection.onopen = function () { 
            connection.send('Ping');
        };

        connection.onerror = function (error) {
            console.log('WebSocket Error ' + error);
        };

        connection.onmessage = function (e) {
            console.log('Server: ' + e.data);
        };

      };
    </script>

2.服务器.py

import socket

HOST = ''
PORT = 9876
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
conn, addr = s.accept()
print 'Connected by', addr
conn.send("Hello")
while 1:
    data = conn.recv(4096)
    print data
    if not data: break
    conn.sendall(data)
conn.close()

启动 server.py 后,它会一直运行,直到我在浏览器中打开 index.html。当我这样做时,我会在控制台上看到以下内容:

WebSocket 连接到“ws://localhost:9876/”失败:
WebSocket 错误 [对象事件]

但是,在另一边(server.py)我得到:

Connected by('127.0.0.1', 55460)GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: localhost:9876
Origin: null
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: WP0GtT0hrdX1bKa0DepOHQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36

Q我的代码有什么问题?我应该如何修改它以便在它们之间进行生物通信?我正在寻找这样的东西:

if data == 'kill': conn.close()

重要编辑

如果我将 index.html 更改WebSocket("ws://localhost:9876/")WebSocket("ws://html5rocks.websocket.org/echo")比它有效。我想这意味着问题出在 server.py 端

线索 #2

如果我WebSocket("ws://localhost/:9876")在 html 中编写,python 代码无法继续该行conn, addr = s.accept()

4

1 回答 1

6

您没有响应标头。尝试 ,

服务器.py

import socket, hashlib, base64, threading

class PyWSock:
    MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
    HSHAKE_RESP = "HTTP/1.1 101 Switching Protocols\r\n" + \
                "Upgrade: websocket\r\n" + \
                "Connection: Upgrade\r\n" + \
                "Sec-WebSocket-Accept: %s\r\n" + \
                "\r\n"
    LOCK = threading.Lock()

    clients = []

    def recv_data (self, client):
        # as a simple server, we expect to receive:
        #    - all data at one go and one frame
        #    - one frame at a time
        #    - text protocol
        #    - no ping pong messages
        data = bytearray(client.recv(512))
        if(len(data) < 6):
            raise Exception("Error reading data")
        # FIN bit must be set to indicate end of frame
        assert(0x1 == (0xFF & data[0]) >> 7)
        # data must be a text frame
        # 0x8 (close connection) is handled with assertion failure
        assert(0x1 == (0xF & data[0]))

        # assert that data is masked
        assert(0x1 == (0xFF & data[1]) >> 7)
        datalen = (0x7F & data[1])

        #print("received data len %d" %(datalen,))

        str_data = ''
        if(datalen > 0):
            mask_key = data[2:6]
            masked_data = data[6:(6+datalen)]
            unmasked_data = [masked_data[i] ^ mask_key[i%4] for i in range(len(masked_data))]
            str_data = str(bytearray(unmasked_data))
        return str_data

    def broadcast_resp(self, data):
        # 1st byte: fin bit set. text frame bits set.
        # 2nd byte: no mask. length set in 1 byte. 
        resp = bytearray([0b10000001, len(data)])
        # append the data bytes
        for d in bytearray(data):
            resp.append(d)

        self.LOCK.acquire()
        for client in self.clients:
            try:
                client.send(resp)
            except:
                print("error sending to a client")
        self.LOCK.release()

    def parse_headers (self, data):
        headers = {}
        lines = data.splitlines()
        for l in lines:
            parts = l.split(": ", 1)
            if len(parts) == 2:
                headers[parts[0]] = parts[1]
        headers['code'] = lines[len(lines) - 1]
        return headers

    def handshake (self, client):
        print('Handshaking...')
        data = client.recv(2048)
        headers = self.parse_headers(data)
        print('Got headers:')
        for k, v in headers.iteritems():
            print k, ':', v

        key = headers['Sec-WebSocket-Key']
        resp_data = self.HSHAKE_RESP % ((base64.b64encode(hashlib.sha1(key+self.MAGIC).digest()),))
        print('Response: [%s]' % (resp_data,))
        return client.send(resp_data)

    def handle_client (self, client, addr):
        self.handshake(client)
        try:
            while 1:            
                data = self.recv_data(client)
                print("received [%s]" % (data,))
                self.broadcast_resp(data)
        except Exception as e:
            print("Exception %s" % (str(e)))
        print('Client closed: ' + str(addr))
        self.LOCK.acquire()
        self.clients.remove(client)
        self.LOCK.release()
        client.close()

    def start_server (self, port):
        s = socket.socket()
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('', port))
        s.listen(5)
        while(1):
            print ('Waiting for connection...')
            conn, addr = s.accept()
            print ('Connection from: ' + str(addr))
            threading.Thread(target = self.handle_client, args = (conn, addr)).start()
            self.LOCK.acquire()
            self.clients.append(conn)
            self.LOCK.release()

ws = PyWSock()
ws.start_server(9876)

关联

我认为最小的 server.py

import socket,hashlib,base64

MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
HSHAKE_RESP = "HTTP/1.1 101 Switching Protocols\r\n" + \
            "Upgrade: websocket\r\n" + \
            "Connection: Upgrade\r\n" + \
            "Sec-WebSocket-Accept: %s\r\n" + \
            "\r\n"

HOST = ''
PORT = 9876
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)
conn, addr = s.accept()
print 'Connected by', addr
data = conn.recv(4096)
headers = {}
lines = data.splitlines()
for l in lines:
    parts = l.split(": ", 1)
    if len(parts) == 2:
        headers[parts[0]] = parts[1]
headers['code'] = lines[len(lines) - 1]
key = headers['Sec-WebSocket-Key']
resp_data = HSHAKE_RESP % ((base64.b64encode(hashlib.sha1(key+MAGIC).digest()),))
conn.send(resp_data)

while 1:
    data = conn.recv(4096)
    if not data: 
        break
    databyte = bytearray(data)
    datalen = (0x7F & databyte[1])
    str_data = ''
    if(datalen > 0):
        mask_key = databyte[2:6]
        masked_data = databyte[6:(6+datalen)]
        unmasked_data = [masked_data[i] ^ mask_key[i%4] for i in range(len(masked_data))]
        str_data = str(bytearray(unmasked_data))
    print str_data
    resp = bytearray([0b10000001, len(str_data)])
    for d in bytearray(str_data):
        resp.append(d)
    conn.sendall(resp)
conn.close()

一次运行。因为不是线程。

于 2013-08-14T20:21:02.270 回答