У меня есть сервер веб-сокета Python и клиент nodejs, и я не могу
реализовать протокольное рукопожатие websocket .
Код сервера Python
Следующий минимальный сервер веб-сокетов использует Flask-sockets
(который использует gevent-websocket
). Имя файла ws_server.py
:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from flask import Flask, request, Response
from flask_sockets import Sockets
app = Flask(__name__)
sockets = Sockets(app)
@sockets.route('/')
def echo_socket(ws):
# print("type request: ",type(request))
# print("dir request: ", dir(request))
print("request.headers: ", request.headers)
# print("type ws: ",type(ws))
# print("dir ws: ",dir(ws))
if hasattr(request, "Sec-Websocket-Protocol"):
print(request.headers["Sec-Websocket-Protocol"])
else:
print("INFO: No protocol specified")
if request.headers["Sec-Websocket-Protocol"] == "aProtocol":
print("INFO: protocol is OK")
else:
print("INFO: protocol not accepted: closing connection")
ws.close()
while not ws.closed:
message = ws.receive()
if message:
print("received: "+message)
ws.send(message)
if ws.closed:
print("INFO: connection has been closed")
if __name__ == "__main__":
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
server = pywsgi.WSGIServer(('', 5001), app, handler_class=WebSocketHandler)
server.serve_forever()
Код клиента nodejs
Следующий минимальный клиент websocket использует websocket
библиотека.
Имя файла app.js
:
'use strict'
var WebSocketClient = require('websocket').client;
var client = new WebSocketClient();
function connectToServer(uri,protocol){
client.on('connectFailed', function (error) {
console.log('Connect Error: ' + error.toString());
});
client.on('connect', function (connection) {
console.log('WebSocket Client Connected');
connection.on('error', function (error) {
console.log("Connection Error: " + error.toString());
});
connection.on('close', function () {
console.log('echo-protocol Connection Closed');
});
connection.on('ping', () => {
connection.pong();
});
connection.on('message', function (message) {
if (message.type === 'utf8') {
console.log("Received message is: '" + message.utf8Data + "'");
}
});
console.log("sending SOMETHING");
connection.sendUTF("SOMETHING");
});
client.connect(uri, protocol);
}
const wsHostAndPort = process.env.WSHSTPRT || "ws://echo.websocket.org:80";
const wsProtocol = process.env.WSPRTCL || []; // [] for no protocol
console.log("connecting to: ",wsHostAndPort,"with protocol",wsProtocol);
connectToServer(wsHostAndPort,wsProtocol);
Соединение с nodejs как клиент
Запустить python ws сервер:
$ python3 ws_server.py
Соединение с nodejs ws client:
$ WSHSTPRT=ws://localhost:5001/ WSPRTCL="aProtocol" node app.js
Вывод клиентского терминала
connecting to: ws://localhost:5001/ with protocol aProtocol
Connect Error: Error: Expected a Sec-WebSocket-Protocol header.
Вывод серверного терминала:
request.headers: Upgrade: websocket
Connection: Upgrade
Sec-Websocket-Version: 13
Sec-Websocket-Key: +QjH5xejDI+OQZQ0OZcWEQ==
Host: localhost:5001
Sec-Websocket-Protocol: aProtocol
INFO: No protocol specified
INFO: protocol is OK
INFO: connection has been closed
Мне кажется, что серверу python нужно установить заголовок с именем
"Sec-WebSocket-Protocol"
с тем же значением, которое он получил от
клиент. Но я не знаю, как это сделать. Я искал в интернете
(в основном форумы flask-sockets
и gevent-websockets
и выпуски
трекеры) пока безуспешно.
Я попробовал другой простой клиент, websocat
. Я вызвал это так:
$ websocat ws://localhost:5001 --protocol aProtocol
Я в интерактивном режиме запросил некоторые сообщения, и они были правильно отображены сервером Python.
Это работает, потому что, я думаю, websocat
(в отличие от nodejs 'websocket
) делает
не ожидать "заголовка Sec-WebSocket-Protocol" в рукопожатии с
сервер.
Но мне нужно использовать клиент nodejs, который ожидает заголовок.
Итак, мой вопрос: как я могу включить "Sec-WebSocket-Protocol"
заголовок в ответе рукопожатия сервера Python?