x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

FSocket in HTML returns false even connection is a success

Currently I'm trying to export a simple topdown template to html5 with a custom written c++ class using FSocket to enable blueprinting tcp sockets for UE4 designers in our company. We have a node.js backend that accepts both TCP and Websocket connections on different ports.

When I run the current game in editor (or export for mac osx), a TCP connection is made and data send and receive has no problems.

However after exporting to HTML5, the websocket connection is made, yet the FSocket->Connect() always return false. There are no logs or errors about the condition of the connection on browser console log, but I can see a successful connection made on the server part.

This is the header that UE4 is sending when game is run in HTML5.

 << IN: 127.0.0.1|56135
 GET / HTTP/1.1
 Upgrade: websocket
 Connection: Upgrade
 Host: 127.0.0.1:8000
 Origin: http://127.0.0.1:55966
 Sec-WebSocket-Protocol: binary
 Pragma: no-cache
 Cache-Control: no-cache
 Sec-WebSocket-Key: MKHvPf1T2PK1Y/j1RaRzxw==
 Sec-WebSocket-Version: 13
 Sec-WebSocket-Extensions: x-webkit-deflate-frame
 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12

Here is the code I'm using to connect to the current backend.

 UTCPSocketNetworking *UTCPSocketNetworking::TCPConnect ()
 {
   // Do not try to connect again
   if ( this->IsConnected ) {
     printGreen("TCPConnect -- Already connected");
     OnSocketConnected.Broadcast();
     return this;
   }
 
   //<editor-fold desc="Check missing variables">
   {
     // Not connected yet
     IsConnected = false;
 
     if ( ServerIP == "" ) {
       printRed("TCPConnect -- ERROR -- Server ip or name is not set yet");
       OnSocketCouldNotConnect.Broadcast();
       return this;
     }
 
     if ( !ServerPort ) {
       printRed("TCPConnect -- ERROR -- Server port is not set yet");
       OnSocketCouldNotConnect.Broadcast();
       return this;
     }
 
     if ( SocketName == "" ) {
       printRed("TCPConnect -- ERROR -- Socket name is not set yet");
       OnSocketCouldNotConnect.Broadcast();
       return this;
     }
   }
   //</editor-fold>
 
   //<editor-fold desc="Create socket">
   {
     FIPv4Address ip;
     FIPv4Address::Parse(ServerIP, ip);
 
     auto LocalAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
     LocalAddress->SetIp(ip.GetValue());
     LocalAddress->SetPort(ServerPort);
     
     Socket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, this->SocketName, false);
     if ( !Socket->Connect(*LocalAddress) ) {
       printRed("TCPConnect -- ERROR -- Could not connect to local address");
       OnSocketCouldNotConnect.Broadcast();
       return this;
     }
   }
   //</editor-fold>
 
   IsConnected = true;
   OnSocketConnected.Broadcast();
 
   return this;
 }


  • This method is called from a blueprint.

  • Socket is an FSocket.

  • ServerIP, ServerPort and SocketName are variables visible for blueprinting.

  • IsConnected is a private variable for checking if socket is connected on c++ side.

  • OnSocketCouldNotConnect and OnSocketConnected are delegates declared via DECLARE_DYNAMIC_MULTICAST_DELEGATE and are working in each case.

  • Experimental HTML5Networking is enabled in Unreal Engine plugins.

  • Tried to run the game in Google, Firefox and Safari, all resulting with the same fail.

Is there any other way of using the FSocket to enable HTML5 networking / websockets ? Are there any tutorials/codes that I can look at for understanding the concept as the documentation does not exist.

Product Version: UE 4.8
Tags:
more ▼

asked Jul 27 '15 at 09:38 AM in C++ Programming

avatar image

emrahgunduz
168 13 15 21

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

Couple of things -

HTML5 networking plugin has nothing to do with what you are trying to do. It is only used for multiplayer. you can safely disable that.

emscripten toolkit wraps websocket with the bsd networking api with a best effort implementation, which is then wrapped by FSocket classes.

The problem which I think you are facing is that there's is no synchronous connect for web sockets and hence the synchronous Connect ( which works on all other platforms as advertised) returns false.

http://kripken.github.io/emscripten-site/docs/porting/guidelines/api_limitations.html#api-limitations

more ▼

answered Jul 27 '15 at 02:24 PM

avatar image

[Ankitkk] STAFF
481 13 3 9

avatar image emrahgunduz Jul 27 '15 at 03:16 PM

Thanks for the reply. So if i'm understanding this correctly, I need to move the socket connection to another thread, and return the received data to main (game) thread with a delegate (or event maybe). Will FRunnableThread be able to achieve this?

avatar image [Ankitkk] STAFF Jul 27 '15 at 03:21 PM

just threading it might not work - HTML5 is single threaded.

basically you need to make this bit of code async

' if ( !Socket->Connect(*LocalAddress) ) { printRed("TCPConnect -- ERROR -- Could not connect to local address"); OnSocketCouldNotConnect.Broadcast(); return this; } } '

This could be replaced by just Socket->Connect(*LocalAddress);

And in the tick function you poll for the connectivity and fire the events when the socket actually connects.

avatar image emrahgunduz Jul 27 '15 at 05:32 PM

After changing the Socket->Connect and trying to poll via tick created other problems.

TCP is still working fine. But this time if the server is unreachable, Unreal Engine is crashing.

After checking, I found out that Socket's connection state is returning SCS_Connected and not SCS_ConnectionError. As the code thinks the connectin was a success, it tries to push messages and crashes.

Also on HTML part, I'm receiving another error from js file. Attached a screen capture, but in short version the error is "Assertion failed: exceptfds not supported".

Any ideas?

alt text

avatar image [Ankitkk] STAFF Jul 27 '15 at 06:03 PM

You can cross reference the minified callstack with the symbols file in - it should be in the same location as the testGame.js to see what exactly is the callstack

https://github.com/kripken/emscripten/blob/667dcd241886fdb878e248d95d8e03abb09c80b7/src/library.js#L7383 - basically exceptfs as a paremter in the select call are is not supported.

With these two pieces of information you should be able to debug.

It maybe that you are using a Select call or FSocket wrapper for the select call automatically adds exceptfds parameter.

If all fails - Look at WebsSocket.cpp specially in code within #PLATFORM_HTML5, we don't use FSocket but just RAW bsd. you maybe able to use just raw BSD for HTML5 code path. for use case, its ugly but may work for your use case.

avatar image emrahgunduz Jul 28 '15 at 11:06 AM

Debugging was taking too long, files are too big for processing. So I decided to take your second suggestion to heart. And it works :)

I created a new class and implemented most of the functionality from WebSocket.cpp. TCP and websocket, both are connecting, sending and receiving data. Just used the "PLATFORM_HTML5_BROWSER" parts... Thanks for that.

But there is something strange with the sent and received buffers. The sent buffer contains some characters (4 chars to be exact) before the data. Something like this:

 L\u0000\u0000\u0000{"namespace": "Login","action": "login","data":{"token": "0"}}

There is nothing on the end. Also the received data gets truncated by the same size, I presume the "L...." is needed on the server part? The returned buffer becomes:

 mespace":"ContinueLogin","action":"savetoken","data":{"token":"127.0.0.1:55404"}}

{"na part from the beginning gets removed...

Do you have any idea where these additional bytes are coming from, and the incoming data gets truncated?

I see that you are padding the data when you are using libwebsocket implementation. Is it possible that sys/socket has something build in?

EDIT: Oh, I'm converting FString to std string. Could this be the problem?

 std::string MyStdString(TCHAR_TO_UTF8(*UE4Str));


EDIT 2: I've replaced TCHAR_TO_UTF8 to TCHAR_TO_ANSI and the 3 byte order marks disappeared. However the "L" is still standing strong. Could this be coming from the StringCast?

Also I'm using built in JSON classes as you can guess. Could TJsonWriter be responsible for the L char?

avatar image emrahgunduz Jul 28 '15 at 02:24 PM

Just saw that the truncation of the incoming message is caused by the OnRawReceive implementation. WebSocket.cpp has a few lines of code for checking if data is waiting.

     uint8 Buffer[1024]; // should be at MAX PACKET SIZE. 
     int Result = recv(SockFd, Buffer, sizeof(uint32), 0);
 
     uint32 DataToBeRead = 0;*(uint32*)Buffer;

As the buffer is read by sizeof(uint32), I'm loosing some data.

  • Added a regex on server side to remove the accessive strings right before { ... }

  • I did not realize the padding was being used to determine the data size :) Nice solution. Implementing this on the server side as well.

Great code, loving this :)

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question