How to disable Nagle algorithm / enable TCP_NoDelay?

Hi, Dear Developers! I am trying to make TCP client on C++, by using this example: link:( A new, community-hosted Unreal Engine Wiki - Announcements - Unreal Engine Forums ). When I send messages to the Server with small intervals, on Server I receive merged Posts like this:

MOVE|0.0|0.0|0.0|0.0 
MOVE|0.0|0.0|0.0|0.0 
MOVE|0.0|0.0|0.0|0.0MOVE|0.0|0.0|0.0|0.0 
MOVE|0.0|0.0|0.0|0.0

To solve this problem I was going to disable Nagle algorithm / enable TCP_NoDelay, but don’t know how. I was looking for method FSocket.setNoDelay(true) or something similar, but have nothing. Who know, where I can find this option for TCP Sockets?

You can consider using delimiting symbol to mark end of message for example instead of trying to find way to disable Nagle’s algorithm.
You could use ~ in the end of each line, so the end of message can be easily parsed.

MOVE|0.0|0.0|0.0|0.0~
MOVE|0.0|0.0|0.0|0.0~
MOVE|0.0|0.0|0.0|0.0~MOVE|0.0|0.0|0.0|0.0~
MOVE|0.0|0.0|0.0|0.0~

Unfortunately (as of v4.10) there is still no way to specify that flag without modifying the Engine source code (look at “Engine\Source\Runtime\Sockets\Private”).

Thanks for such a detailed answer! I still believe that it does not make much sense to alter Engine by ourselves as it could make future updates difficult, but it is a great chance to understand the Engine internals better

(fun fact, we have worked on this question for TCP networking PoC back in 2015 and abandoned the project a couple of weeks later, so never had a chance to dive deep enough into it)

oh, sorry I understood the wrong way after seeing

This will also not work if future Unreal version move the Winsock so that it’s not the first member of FSocketBSD

I have not worked with UE4 more than three years, so I just read the overall text quickly enough to skip some important details.
My thoughts here generally are that it is not a good idea in most cases to be dependent on some specifics of the current version of the Engine if it could be subject to change in the future.

This is for windows only:

If you can get the Winsock from your FSocket instance then you can disable Nagle’s algorithm by yourself. Unfortunately the Winsock is not a member of FSocket, but it is a member of FSocket’s Windows specific derivation FSocketBSD. But Unreal Engine does not expose this type so you can’t use it in your code without changing the engine source.

So here’s how to disable Nagle’s algorithm without changing the engine source :slight_smile:

// Build listener socket...
FSocket *listener = ....;

// Move the listener pointer to right after your FSocket instance and cast it to a UINT_PTR
UINT_PTR nativeSocket = *((UINT_PTR*)(listener + 1));

// Disable Nagle's algorithm
int flag = 1;
int result = setsockopt(nativeSocket, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
int err = WSAGetLastError();

// In case you messed something up
if (result < 0)
    UE_LOG(LogTemp, Warning, TEXT("Error code %d"), err);

Here are the Winsock error codes in case you need to debug something. This works because FSocketBSD is derived from FSocket and the Winsock is the first member of FSocketBSD. Since member variables are laid out in memory in the order they are defined (*most of the time), the first value in memory after your FSocket will be the first member of FSocketBSD. I said *most of the time because the layout of memory can depend on the compiler and compiler options. This will also not work if future Unreal version move the Winsock so that it’s not the first member of FSocketBSD, though this can be fixed by simply moving the pointer to it’s new location.

Not sure if I misunderstand your comment or if I explained poorly, but by doing this you can disable Nagle’s algorithm without altering the Engine. I’ll edit my asnwer anyways to make it more clear.

This is true, but also easily patched by adding preprocessor macros for different versions if they decide to restructure FSocketBSD in the future.

#if ENGINE_MINOR_VERSION < 22
// Move pointer to right location
#endif
#if ENGINE_MINOR_VERSION >= 22
// Move pointer to new right location
#endif