IXWebSocket icon indicating copy to clipboard operation
IXWebSocket copied to clipboard

No Close event for IXWebSocket client (11.4.2) when server disconnects

Open mwinch2 opened this issue 2 years ago • 6 comments

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();
}

mwinch2 avatar Jun 24 '22 08:06 mwinch2

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 ?

bsergean avatar Jun 30 '22 08:06 bsergean

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 :)

mwinch2 avatar Jun 30 '22 09:06 mwinch2

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.

bsergean avatar Jun 30 '22 17:06 bsergean

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).

bsergean avatar Jun 30 '22 17:06 bsergean

I can confirm Close event happening for Windows using vcpkg x86-windows-static with IXWebSocket v 11.4.3

hamzaahmedzia1 avatar Aug 02 '22 13:08 hamzaahmedzia1

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.

mwinch2 avatar Aug 02 '22 15:08 mwinch2