POCO 1.5.1 Клиент Websocket не может подключиться к серверу c # websocket

Проблема:

Клиент websocket (POCO 1.5.1, c ++) не будет подключаться к серверу websocket c # (приложение командной строки с библиотекой Fleck). Тайм-аут достигается с исключением:

Cannot upgrade to WebSocket connection: OK
Exception Code: 1

Poco WebException Documentation
WS_ERR_NO_HANDSHAKE = 1 :
No Connection: Upgrade or Upgrade: websocket header in handshake request.

Факт 1: Это клиент websocket подключится к Ruby Event Machine сервер веб-сокетов.

Факт 2: A клиент javascript подключится к сервер websocket c #.

Факт 3: Такой же клиент javascript также подключится к рубиновый сервер websocket.

Факт 4: клиент websocket не будет подключаться к Алхимия Websocket сервер neigther. https://github.com/Olivine-Labs/Alchemy-Websockets

Обновление с Wireshark
POCO использует
GET / HTTP / 1.0 \ r \ n

Версия Javascript:
GET / HTTP / 1.1 \ r \ n


Код клиента в с ++

#include "Game.h"
#include <irrlicht.h>
#include "driverChoice.h"#include <iostream>
#include <assert.h>

#include "Poco/Net/WebSocket.h"#include "Poco/Net/HTTPClientSession.h"#include "Poco/Net/HTTPRequest.h"#include "Poco/Net/HTTPResponse.h"#include "Poco/Net/ServerSocket.h"#include "Poco/Net/NetException.h"#include "Poco/Exception.h"
using Poco::Net::HTTPClientSession;
using Poco::Net::HTTPRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPServerResponse;
using Poco::Net::WebSocket;
using Poco::Net::WebSocketException;
using Poco::Exception;

// VS2010
// POCO 1.5.1
// Irrlicht 3D engine
// Windows 7 Enterprise edition

Game::Game(void)
{
}

Game::~Game(void)
{
}

//...

void Game::TestWebSocketClient()
{
char buffer[1024];
int flags;
int n;
std::string payload;

try
{
HTTPClientSession cs("localhost", 8080);
HTTPRequest request(HTTPRequest::HTTP_GET, "/ws");
HTTPResponse response;
std::string cmd;

WebSocket * ws = new WebSocket(cs, request, response); // Causes the timeout

payload = "SGClient: Hello World!";
ws->sendFrame(payload.data(), payload.size(), WebSocket::FRAME_TEXT);
n = ws->receiveFrame(buffer, sizeof(buffer), flags);

while( cmd != "exit")
{
cmd = "";
std::cin >> cmd;
ws->sendFrame(cmd.data(), cmd.size(), WebSocket::FRAME_TEXT);
n = ws->receiveFrame(buffer, sizeof(buffer), flags);
if( n > 0 )
{
std::cout << buffer << std::endl;
}
}

ws->shutdown();
}
catch (Exception ex)
{
return;
}

Код сервера в c #

// vs2010
// fleck library
// Windows 7 enterprise editionusing System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Fleck;
using System.Timers;

namespace TestWebsocket
{
class Program
{
static void Main()
{
FleckLog.Level = LogLevel.Debug;
var allSockets = new List<IWebSocketConnection>();
var server = new WebSocketServer("ws://localhost:8080");
server.Start(socket =>
{
socket.OnOpen = () =>
{
Console.WriteLine("Open!");
allSockets.Add(socket);
};
socket.OnClose = () =>
{
Console.WriteLine("Close!");
allSockets.Remove(socket);
};
socket.OnMessage = message =>
{
Console.WriteLine(message);
allSockets.ToList().ForEach(s => s.Send("Echo: " + message));
};
});

var input = Console.ReadLine();
while (input != "exit")
{
foreach (var socket in allSockets.ToList())
{
socket.Send(input);
}
input = Console.ReadLine();
}

}
}
}

Альтернативный клиентский код HTML / Javascript, работающий в Chrome версии 31.0.1650.57 m

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>websocket client</title>
<script type="text/javascript">
var start = function () {
var inc = document.getElementById('incomming');
var wsImpl = window.WebSocket || window.MozWebSocket;
var form = document.getElementById('sendForm');
var input = document.getElementById('sendText');

inc.innerHTML += "connecting to server ..<br/>";

// create a new websocket and connect
window.ws = new wsImpl('ws://localhost:8080/');

// when data is comming from the server, this metod is called
ws.onmessage = function (evt) {
inc.innerHTML += evt.data + '<br/>';
};

// when the connection is established, this method is called
ws.onopen = function () {
inc.innerHTML += '.. connection open<br/>';
};

// when the connection is closed, this method is called
ws.onclose = function () {
inc.innerHTML += '.. connection closed<br/>';
}

form.addEventListener('submit', function(e){
e.preventDefault();
var val = input.value;
ws.send(val);
input.value = "";
});

}
window.onload = start;
</script>
</head>
<body>
<form id="sendForm">
<input id="sendText" placeholder="Text to send" />
</form>
<pre id="incomming"></pre>
</body>
</html>

Альтернативный код сервера ruby ​​с использованием машины событий, работающей в интерфейсе командной строки

// Ruby 1.9
// gem install em-websocket required.
require 'em-websocket'

EventMachine::WebSocket.start(:host => "localhost", :port => 8080) do |ws|
ws.onopen    { ws.send "RS: Hello Client!"}
ws.onmessage {
|msg| ws.send "RS: Pong: #{msg}"puts msg
}
ws.onclose   { puts "WebSocket closed" }
end

5

Решение

Проблема заключалась в том, что версия HTTP-запроса POCO по умолчанию была 1.0.

Раздел 4.1 спецификации RFC указывает, что минимум равен 1.1:

http://tools.ietf.org/html/rfc6455#section-4.1

  1. Метод запроса ДОЛЖЕН быть GET, а версия HTTP ДОЛЖНА
    быть хотя бы 1.1.
    Например, если URI WebSocket имеет вид «ws: //example.com/chat»,
    первая отправленная строка должна быть «GET / chat HTTP / 1.1».

Проблема была решена путем замены конструкции HTTPRequest на:

HTTPRequest request(HTTPRequest::HTTP_GET, "/ws", "HTTP/1.1" );

Ура!

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]