WebSockets module not loaded properly in packaged builds only. Other modules OK

We have observed that the WebSockets module (and only this module) is not properly loaded in a packaged build. To compare with a “good” module we are also loading the Http module (In our tests we loaded many more modules and only had issues with the WebSockets module).

We have setup an empty C++ project with the following *.Build.cs file:



// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class WSTest : ModuleRules
{
    public WSTest(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        PublicDependencyModuleNames.AddRange(new string] { "Core", "CoreUObject", "Engine", "InputCore", "Http", "WebSockets" });

        PrivateDependencyModuleNames.AddRange(new string] {  });

        // Uncomment if you are using Slate UI
        // PrivateDependencyModuleNames.AddRange(new string] { "Slate", "SlateCore" });

        // Uncomment if you are using online features
        // PrivateDependencyModuleNames.Add("OnlineSubsystem");

        // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
    }
}


And an Actor class that was added to the scene:



// Fill out your copyright notice in the Description page of Project Settings.


#include "MyActor.h"
#include "WebSocketsModule.h"
#include "Http.h"

// Sets default values
AMyActor::AMyActor()
{
     // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
    Super::BeginPlay();

#if WEBSOCKETS_PACKAGE==1
    UE_LOG(LogTemp, Warning, TEXT("WEBSOCKETS_PACKAGE=1")); //prints in all cases
#endif

#if defined(WITH_WEBSOCKETS)
    #if WEBSOCKETS_PACKAGE==1
    UE_LOG(LogTemp, Warning, TEXT("WEBSOCKETS_PACKAGE=1")); //prints in all cases
    #endif
#endif

#if defined(WITH_LIBWEBSOCKETS)
    #if WITH_LIBWEBSOCKETS==1
    UE_LOG(LogTemp, Warning, TEXT("WITH_LIBWEBSOCKETS=1")); //prints in all cases
    #endif
#endif

    FWebSocketsModule* wsModule = &FWebSocketsModule::Get();
    if (wsModule == nullptr) {
        UE_LOG(LogTemp, Warning, TEXT("wsModule is null")); //prints in packaged build
    } else {
        UE_LOG(LogTemp, Warning, TEXT("wsModule is valid")); //prints in editor

        TMap<FString, FString> headers;
        headers.Add("Upgrade", "Websocket");

        TSharedPtr<IWebSocket> ws = wsModule->CreateWebSocket(TEXT("ws://whatever.com:80"), TEXT("NULL"), headers);
    }

    FHttpModule* Http = &FHttpModule::Get();
    if (Http == nullptr) {
        UE_LOG(LogTemp, Warning, TEXT("http is not valid"));
    } else {
        UE_LOG(LogTemp, Warning, TEXT("http is valid")); //prints in all cases
        TSharedRef<IHttpRequest> Request = Http->CreateRequest();
    }
}

// Called every frame
void AMyActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}


This was tested in UE 4.22 (from source) and 4.24 (from standard Epic download)

We suspected there was an issue when populating the AdditionalLibraries list in the UnrealBuildTool so we added some Log.TraceWarning lines at the end of the protected virtual void SetupPublicLinkEnvironment function in UEBuildModule.cs:630 but the libWebSockets library was being loaded properly as per the libWebSockets.Build.cs

Running a debugger on our actor shows that this line:


FWebSocketsModule* wsModule = &FWebSocketsModule::Get();

returns null on packaged builds (in any deployment setting) but will work in editor.

But this line:


FHttpModule* Http = &FHttpModule::Get();

presents no issues.

The FWebSocketsModule::Get function does return the Singleton of the module but it would seem the singleton itself is not set. We suspect the void FWebSocketsModule::StartupModule() function is not getting called but there is a knowledge gap as to what calls it, how, and when. If anyone knows how modules are loaded and started help here would be a good way to point us in the right direction unless this is an outright bug.

In any case, since other modules load correctly except for this one, would this be something to file as a bug?

Any help appreciated,
thanks.

hi, i had same issue.
after a day searching, debug and tracing finally i have it done.
as you say the issue was Websocket module wasn’t loaded. so by using ModuleManager and load it on runtime made it work. :smiley:


#include "Modules/ModuleManager.h"


if(!FModuleManager::Get().IsModuleLoaded("WebSockets"))
{
     FModuleManager::Get().LoadModule("WebSockets");
     WebSocket = &FWebSocketsModule::Get();
}

7 Likes

Hi,
I followed @'s solution and it worked like a charm. you for sharing, much appreciated! :wink:

Just had the same issue, thanks to @Arshavin. answer it solved the problem!

@Arshavin. ~~
Hello ~ can you tell me your path?? If where do you want to put it?? I tried to put it in

#if WITH_ Below the end of engine, but I made an error when packing

Can you tell me ~ where you put it?? After I looked up and put it in, I found a packaging error and couldn’t return

For simplicity Just use this code before instantiation of the WebSocket instance in your game code.
The below code is more convenient:

FWebSocketsModule* WebSocketModule = &FModuleManager::LoadModuleChecked<FWebSocketsModule>(TEXT("WebSockets"));
if(WebSocketModule ){
        this->WebSocket = WebSocketModule->CreateWebSocket(... your server url and other params
}

We just got in touch with UE, so we don’t know where to instantiate this code, ~ can you answer exactly where to instantiate it ~ ~ y

Check this link
https://unrealcommunity.wiki/websocket-client-cpp-5vk7hp9e

This is a client. Which line of the code file should this string of code be placed on

Just before creating the socket object. That is the point where the socket object is instantiating.
consider the function " CreateWebSocket(ServerURL, ServerProtocol); "
Just place your code into the If block statement of my code.

We are the server ~ ~ the content of this link is the client

For the Server, you need to develop Backend part with the web framework or any programming language of your choice. although for testing purposes you can find a Demo or tutorial on the internet.

I think it’s better that you realize what are you want to do and then start with the unreal engine programming fundamentals. there are lots of tutorials and courses you can find on the internet, youtube, and the unreal engine online learning site itself.

Hope you doing well.

I actually noticed the same thing myself just recently. The answer is quite easy: It’s a bug. The ::Get() method should load the module if it was not loaded before, but it doesn’t. And even worse: It actually dereferences a nullptr in that case.

I made a merge request with a fix for this. In the meanwhile you can just add a line with FModuleManager::Get().LoadModuleChecked("WebSockets"); right before the FWebSocketsModule* wsModule = &FWebSocketsModule::Get(); line to ensure that it is loaded before accessing it.

For tracking, here is the PR: https://github.com/EpicGames/UnrealEngine/pull/9376

i have a same issue too, thank you @Arshavin.Zohrabi
i add your code on my custom c++ file , and it work now , even packaged, i think it need load websocket first only can create connection

if (url == “open”) {

	FWebSocketsModule* WebSocketModule = &FModuleManager::LoadModuleChecked<FWebSocketsModule>(TEXT("WebSockets"));
	if (WebSocketModule) {

	

	if (!FModuleManager::Get().IsModuleLoaded("WebSocket"))
	{
		FModuleManager::Get().LoadModule("WebSocket");
	}

	WebSocketConnection = FWebSocketsModule::Get().CreateWebSocket(WebsocketURL);

	WebSocketConnection->OnConnected().AddLambda([]
		{
			//UE_LOG(LogTemp, Warning, TEXT("Successfully Connected"));
		});

	OnMessageLambda = [&](const FString& MessageString)
	{
		//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Cyan, "Websocket open: " + MessageString);
		receive = MessageString;
		WebSocketConnection->OnMessage().Clear();
	};

	WebSocketConnection->OnMessage().AddLambda(OnMessageLambda);


	WebSocketConnection->Connect();

	}
}