IXWebSocket
IXWebSocket copied to clipboard
No Close event for IXWebSocket client (11.4.2) when server disconnects
When using version 11.4.2 an IXWebSocket client does not get a Close notification when the server disconnects. IXWebSocket was built via vcpkg, with triplet x64-windows-static, using VS2015.
I have built a simple client based on the example code. The code is shown below. I had version 7.9.2 available from an older project and tried that, and it worked fine.
For the server I am using a simple nodejs script which just echoes anything received.
As a workaround I have set a short ping time - the Close notification is generated when the ping fails after the server has disconnected. Let me know if you need any more info.
// IXWebsocketClient.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <ixwebsocket/IXWebSocket.h>
#include <ixwebsocket\IXNetSystem.h>
#include <conio.h>
#include <windows.h>
int main()
{
ix::initNetSystem();
// Our websocket object
ix::WebSocket webSocket;
std::string url("ws://localhost:8088/");
webSocket.setUrl(url);
// Optional heart beat, sent every 45 seconds when there is not any traffic
// to make sure that load balancers do not kill an idle connection.
webSocket.setPingInterval(45);
// Per message deflate connection is enabled by default. You can tweak its parameters or disable it
webSocket.disablePerMessageDeflate();
bool connected = false;
// Setup a callback to be fired when a message or an event (open, close, error) is received
webSocket.setOnMessageCallback([&](const ix::WebSocketMessagePtr& msg)
{
if (msg->type == ix::WebSocketMessageType::Message)
{
std::cout << msg->str << std::endl;
}
else if (msg->type == ix::WebSocketMessageType::Open)
{
std::cout << "connected" << std::endl;
connected = true;
}
else if (msg->type == ix::WebSocketMessageType::Close)
{
std::cout << "disconnected" << std::endl;
// The server can send an explicit code and reason for closing.
// This data can be accessed through the closeInfo object.
std::cout << msg->closeInfo.code << std::endl;
std::cout << msg->closeInfo.reason << std::endl;
}
}
);
// Now that our callback is setup, we can start our background thread and receive messages
webSocket.start();
while (!connected)
{
Sleep(100);
}
// Send a message to the server (default to TEXT mode)
webSocket.send("hello world");
// The message can be sent in BINARY mode (useful if you send MsgPack data for example)
//webSocket.sendBinary("some serialized binary data");
std::cout << "Press any key to continue...";
_getch();
// Stop the connection
webSocket.stop();
}
Thanks for the report. If things worked in an earlier version, we should be able to find which code change triggered the bug.
We changed a few things on Windows recently, maybe it broke things. Does the bug happens on linux as well ?
I'm only working on Windows, so I'm not sure. Looking at the changelog, 11.4.0 looks a candidate due to Windows changes to use WSAEventSelect. I haven't had a chance to try 11.3.2 - I started looking at how to get specific library versions via vcpkg but that's much more fiddly than I thought it would be :)
Ah thank you for digging, the introduction of WSAEventSelect could be the problem but it's a wild guess.
I do most of my development on mac and linux so it's always hard for me to test regressions. But we do have a test suite for a few windows configurations, adding a simple unittest to check that we get server close events would be good.
There's such a unittest, but it's been disabled on windows for a long time ... (it probably was always disabled).
# Some unittest don't work on windows yet
# Windows without TLS does not have hmac yet
if (UNIX)
list(APPEND TEST_TARGET_NAMES
IXWebSocketCloseTest
If we can make this work it would be really great (by that fix the bug and enable that unittest).
I can confirm Close event happening for Windows using vcpkg x86-windows-static with IXWebSocket v 11.4.3
I've just tried again with 11.4.3 (both x64-windows-static and x86-windows-static) and there is no change of behaviour with the above client code for me.
I should be clearer in what my test is though - I am actually killing the server process, so the socket is closed. If the server shuts down cleanly and sends a WebSocket Connection Close, then IXWebSocket does detect that.