POCO 1.5.1 Websocket client unable to connect to c# websocket server

c#, c++, eventmachine, poco, websocket

Solution

The problem was that POCO default HTTP request version was 1.0.

Section 4.1 of the RFC specs indicates that minimum is 1.1:

https://www.rfc-editor.org/rfc/rfc6455#section-4.1

- The method of the request MUST be GET, and the HTTP version MUST be at least 1.1. For example, if the WebSocket URI is "ws://example.com/chat", the first line sent should be "GET /chat HTTP/1.1".

Problem was solved by replacing the HTTPRequest construction by:

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

Cheers!

Problem

Problem: A websocket client(POCO 1.5.1, c++) will not connect to a websocket c# server (command line app with Fleck Library). A timeout is reached with an exception thrown: ``` 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. ``` Fact 1: This websocket client will connect to a Ruby Event Machine websocket server. Fact 2: A javascript client will connect to the websocket c# server. Fact 3: The same javascript client will also connect to the websocket ruby server. Fact 4: The websocket client will not connect to an Alchemy Websocket server neigther. https://github.com/Olivine-Labs/Alchemy-Websockets Update with Wireshark POCO is using GET / HTTP/1.0\r\n Javascript version: GET / HTTP/1.1\r\n All Source Code Client code in c++ ``` #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; } ``` Server code in c# ``` // vs2010 // fleck library // Windows 7 enterprise edition using 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(); } } } } ``` Alternate HTML/Javascript client code, running in Chrome Version 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> ``` Alternate ruby server code using eventmachine running on command line interface ``` // 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 ```

Original source