Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Best HTTP Released

Discussion in 'Assets and Asset Store' started by BestHTTP, Sep 11, 2013.

  1. CAREFiSH

    CAREFiSH

    Joined:
    May 28, 2013
    Posts:
    8
  2. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @CAREFiSH I would take a breakpoint in the server function to see whether it called or not. Changing Invoke's type parameter doesn't change how it's sending the data, only how it tries to parse the received one.

    You can also set the plugin's log level to verbose and send the produced log to me, so i might have more clues about what's going on. You can read about the plugin's logging and how to change it here: https://besthttp-documentation.readthedocs.io/en/latest/#7.GlobalTopics/Logging/
     
  3. CAREFiSH

    CAREFiSH

    Joined:
    May 28, 2013
    Posts:
    8
    @BestHTTP Here is the logfile, https://gist.github.com/carefish/7cad8a420cfd00acf73a7f2588ca392e#file-besthttp-log. The breakpoint does not get hit, which is what I am confused about: I left a test Echo function on the Hub and that one does hit a breakpoint and returns the 'hello from client' message just fine.

    Edit: The file I am trying to send is 162KB big, could that be what's causing my problems?
    Edit2: That looks to be the cause of my issues. Thanks for your amazing plugin, and quick responses and fast support.

    For future reference for users:
    Code (CSharp):
    1. services.AddSignalR(options =>
    2. {
    3.                 options.MaximumReceiveMessageSize = 327680;//double check what your project needs and adjust accordingly. SignalR (Core) was not designed for really big messages so keep that in mind.
    4. }).AddMessagePackProtocol();
     
    Last edited: Jan 28, 2021
  4. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @CAREFiSH Nice, didn't know about MaximumReceiveMessageSize.
     
  5. CAREFiSH

    CAREFiSH

    Joined:
    May 28, 2013
    Posts:
    8
    @BestHTTP I am reading https://besthttp-documentation.read...bConnection/#streaming-to-and-from-the-server, however GetUpAndDownStreamController() seems missing?

    Edit: I wasn't calling it properly. I mean, I didn't first try the sample properly before making my own changes. I thought
    Code (CSharp):
    1. GetUpAndDownStreamController<string, string>
    could be
    Code (CSharp):
    1. GetUpAndDownStreamController<MyType, MyOtherType>
    Edit2: I don't understand why the following code does not work, but does work when I replace all of the 'Vec3' instances with string instances.
    https://gist.github.com/carefish/ba0047ffe941d47adfef5dd4be273349
     
    Last edited: Jan 31, 2021
  6. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @CAREFiSH How your Vec3 looks like? Just made a quick and dirty test to rewrite the UploadWord functions and it's worked as expected.

    Client:
    Code (CSharp):
    1. private IEnumerator UploadWord()
    2. {
    3.     AddText("<color=green>UploadWord</color>:");
    4.  
    5.     var controller = hub.GetUpStreamController<Vec3, Vec3>("UploadWord");
    6.     controller.OnSuccess(result =>
    7.         {
    8.             AddText(string.Format("UploadWord completed, result: '<color=yellow>{0}</color>'", result))
    9.                 .AddLeftPadding(20);
    10.             AddText("");
    11.  
    12.             StartCoroutine(ScoreTracker());
    13.         });
    14.  
    15.     controller.UploadParam(new Vec3() { x = 3, y = 2, z = 1 });
    16.  
    17.  
    18.     yield return new WaitForSeconds(_yieldWaitTime);
    19.  
    20.     controller.Finish();
    21.  
    22.     AddText("Sent upload finished message.")
    23.         .AddLeftPadding(20);
    24.  
    25.     yield return new WaitForSeconds(_yieldWaitTime);
    26. }
    Server:
    Code (CSharp):
    1. public async Task<Vec3> UploadWord(ChannelReader<Vec3> source)
    2. {
    3.     //var sb = new StringBuilder();
    4.  
    5.     // receiving a StreamCompleteMessage should cause this WaitToRead to return false
    6.     while (await source.WaitToReadAsync())
    7.     {
    8.         while (source.TryRead(out var item))
    9.         {
    10.             Debug.WriteLine($"received: {item}");
    11.             Console.WriteLine($"received: {item}");
    12.  
    13.             //sb.Append(item);
    14.         }
    15.     }
    16.  
    17.     // method returns, somewhere else returns a CompletionMessage with any errors
    18.     return new Vec3();
    19. }
    Vec3 is the same on both side:
    Code (CSharp):
    1. public class Vec3
    2. {
    3.     public float x, y, z;
    4. }
    upload_2021-1-31_9-12-37.png upload_2021-1-31_9-13-17.png
     
  7. CAREFiSH

    CAREFiSH

    Joined:
    May 28, 2013
    Posts:
    8
    @BestHTTP Copy/pasted your code now as well, and on my end the server is just getting zeroes. https://gyazo.com/77d8625ea6a0b4232dd6bf19b22581b1 Top part of the GIF shows Unity client with a Debug.Log() in the IEnumerator UploadWord(). Lower part of the GIF shows console output from the servers' UploadWord.

    This is my Vec3:

    Code (CSharp):
    1.     public class Vec3
    2.     {
    3.         public float x { get; set; }
    4.         public float y { get; set; }
    5.         public float z { get; set; }
    6.         public override string ToString()
    7.         {
    8.             return $"x: {x} y: {y} z:{z}";
    9.         }
    10.     }
    ... I fixed it, it indeed was a mistake in my Vec3 class. Sincerest apologies for bothering you with easy to fix problems.
     
  8. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
  9. bdae

    bdae

    Joined:
    Dec 24, 2017
    Posts:
    23
    Whats the socket.io code for the server supposed to look like in javascript?
    I have the socket created and listening for the connecting event but nothing shows up.

    Server code:
    Code (JavaScript):
    1. const options = { /* ... */ };
    2. const io = require('socket.io')(3000, options);
    3. io.on('connection', socket => {
    4. console.log("Connection Received");
    5.  
    6. });
    Client code:
    Code (CSharp):
    1. public SocketManager manager;
    2.  
    3. void Start()
    4. {
    5. manager = new SocketManager(new System.Uri("https://localhost:3000"));
    6. }
    7.  
    If I add SocketIOEventTypes.Error listener thing, unity console returns: Error: Code: Internal Message: "unexpected_message(10)..."

    Edit: So I noticed I needed to use the /socket.io path in the Uri and I added that in there. I now get 'Connection' events but in unity it is telling me that the connection timed out.
     
    Last edited: Feb 2, 2021
  10. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @bdae Yes, the /socket.io/ path is required, that's where the server is bound to by default. What Socket.IO version of your server is using? Is specify it in the SocketOption resolves it?

    Code (CSharp):
    1. SocketOptions options = new SocketOptions();
    2. options.ServerVersion = SupportedSocketIOVersions.v3;
    3.  
    4. var manager = new SocketManager(new Uri("http://localhost:3000/socket.io/"), options);
     
  11. bdae

    bdae

    Joined:
    Dec 24, 2017
    Posts:
    23
    I tried updating my post saying I fixed that problem but it told me I couldnt due to spam or something. I solved it by removing those options, I had set them while trying to figure it out and removing them fixed it for me.
    I'm having another issue now though, I'm trying to send an array through nodejs server to my unity client and I dont know how to get the array out of it. So far I have only managed to get it as a string.
     
  12. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
  13. bdae

    bdae

    Joined:
    Dec 24, 2017
    Posts:
    23
    How do I get the bytes into a List?
     
  14. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @bdae The Attachments property is a List of Byte arrays. Each byte[] is a binary field or parameter sent by the server. You can convert those byte arrays to whatever you want and can.
     
  15. bdae

    bdae

    Joined:
    Dec 24, 2017
    Posts:
    23
    I must be missing something.
    Attachments return null.
    Code (CSharp):
    1. void handleArray(Socket socket, Packet packet, params object[] args)
    2.     {
    3.         Debug.Log(packet);//["event_name","[\"username1\",\"username2\"]"]
    4.         Debug.Log(packet.Attachments);//Null
    5.         Debug.Log(packet.AttachmentCount);//0
    6.         Debug.Log(packet.Attachments[0]); //Missing object reference
    7.         // Replace the Json object with the index
    8.         packet.ReconstructAttachmentAsIndex();
    9.         // now, decode the Payload to an object[]
    10.         args = packet.Decode(socket.Manager.Encoder);
    11.         // args now contains only an index number (probably 0)
    12.         byte[]data = packet.Attachments[Convert.ToInt32(args[0])]; //Specified cast is not valid
    13.     }
    This also doesn't seem to work:

    Code (CSharp):
    1. void handleArray(Socket socket, Packet packet, params object[] args)
    2.     {
    3.        
    4.         // Replace the Json object with the index
    5.         packet.ReconstructAttachmentAsIndex();
    6.         // now, decode the Payload to an object[]
    7.         args = packet.Decode(socket.Manager.Encoder);
    8.         // args now contains only an index number (probably 0)
    9.         byte[]data = packet.Attachments[Convert.ToInt32(args[0])]; //Specified cast is not valid
    10.     }
     
  16. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @bdae Could you show your server side code (what and how you sending) too?
     
  17. bdae

    bdae

    Joined:
    Dec 24, 2017
    Posts:
    23
    I'm sending it like this:
    Code (JavaScript):
    1. let usernameList = ["Username1", "Username2"];
    2. socket.emit("event_name", usernameList)
     
  18. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @bdae Those are in the third 'args' parameters. You mentioned arrays and bytes and i thought you want to send binary data. Sent binary can be accessed through the Packet's Attachments array, but otherwise the sent parameters are in the args array of the callback.
     
  19. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @bdae

    Code (CSharp):
    1. manager.Socket.On("event_name", OnEvent_name);
    2.  
    3. private void OnEvent_name(Socket socket, Packet packet, object[] args)
    4. {
    5.     var eventNames = args[0] as List<object>;
    6.  
    7.     foreach (var name in eventNames)
    8.         Debug.Log(name.ToString());
    9. }
     
  20. bdae

    bdae

    Joined:
    Dec 24, 2017
    Posts:
    23
    For some reason that gave me an object reference error. I had to use:

    Code (CSharp):
    1. object[] usernames = (object[])args[0];
    2. foreach(var name in usernames)
    3.         {
    4.             Debug.Log(name.ToString());
    5.         }
    Do you know why that might be?
     
  21. Mihaylevskiy

    Mihaylevskiy

    Joined:
    Aug 30, 2017
    Posts:
    6
    Hi,
    var request = {
    ':method' : 'POST',
    ':scheme' : 'https',
    ':path' : '/v20160207/events',
    'authorization' : 'Bearer <valid token>',
    'content-type' : 'multipart/form-data; boundary=this-is-my-boundary-for-alexa'
    };
    How to implement this? (HTTP/2)
     
  22. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @bdae Don't know it should be a List.
     
  23. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @Mihaylevskiy

    The plugin upgrades and uses HTTP/2 whenever it's possible. The request would look something like this:
    Code (CSharp):
    1. var request = new HTTPRequest(new Uri("https://server/v20160207/events"), HTTPMethods.Post, OnRequestFinished);
    2.  
    3. request.AddHeader("authorization", "Bearer " + validToken);
    4.  
    5. request.FormUsage = BestHTTP.Forms.HTTPFormUsage.Multipart;
    6. //request.AddField("field name", "value");
    7. //request.AddBinaryData("field name", new byte[] { });
    8.  
    9. request.Send();
     
  24. blanx

    blanx

    Joined:
    Feb 26, 2016
    Posts:
    68
    Hi,

    I am using something like this to send stream data to the unity socket.io clients, but the event is never executed there.
    I think its related to "ss(io.to(clientId)).emit". If I use "io.clientId.emit" instead, the package will be received. Is there anything else I have to set up to support streams?

    Thanks

    Code (CSharp):
    1.   ss(socket).on('stream-speech', async function (stream, data) {
    2.     const tempStream = stream
    3.     const filename = path.basename(data.name)
    4.     console.log(new Date().toISOString(), 'stream-speech')
    5.     stream.pipe(fs.createWriteStream(filename))
    6.  
    7.     clients.forEach(clientId => {
    8.       if (clientId !== socket.id) {
    9.         console.log('emit', clientId)
    10.         var outgoingstream = ss.createStream();
    11.         ss(io.to(clientId)).emit('stream-speech-spread', outgoingstream, data);
    12.         stream.pipe(outgoingstream);
    13.      
    14.         outgoingstream.on('data', function(data) {
    15.           console.log('data')
    16.  
    17.           for(var i=0;i<data.length;i++) {
    18.             binaryString+=String.fromCharCode(data[i]);
    19.           }
    20.  
    21.         });
    22.      
    23.       }
    24.     })
    25.   })
     
  25. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @blanx

    Socket.IO-Stream is a non-official extension to the Socket.IO protocol and both the server and client have to support it. While the plugin has no direct support for stream, it uses regular socket.io events wouldn't be too hard to write a similar extension on top of the plugin to support it.
     
  26. blanx

    blanx

    Joined:
    Feb 26, 2016
    Posts:
    68
    Don't know if this is beyond my knowledge. Now I added callbacks for "$stream" and "$stream-read", but I don't know where I can find the data of the stream.

    ["$stream","stream-speech-spread",{"$stream":"77beafdf-37b0-4b33-ad35-87df13d99701"},{"name":"_temp/stream.wav","size":3016}]

    ["$stream-read","77beafdf-37b0-4b33-ad35-87df13d99701",16384]

    that's all I have for now.
     
  27. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
  28. Mihaylevskiy

    Mihaylevskiy

    Joined:
    Aug 30, 2017
    Posts:
    6
    Hi,
    I, see warning:
    Data sending halted for this round. Remote Window: 10 593, frame: [HTTP2FrameHeaderAndPayload Length: 16383, Type: DATA, Flags: 00000000

    and set parameter HTTPManager.HTTP2Settings.MaxFrameSize = xxxx
    but in function below maxFrameSize always [HTTP2Settings.MAX_FRAME_SIZE] = 16384. It is right?

    private void CreateHeaderFrames(....)
    {
    ------
    UInt32 maxFrameSize = this.settingsRegistry.RemoteSettings[HTTP2Settings.MAX_FRAME_SIZE];
    ------
    }
     
  29. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @Mihaylevskiy You can ignore that warning and shouldn't change anyt settings because of this.
    This is logged out when the client semt more than the server could proccess, so the client have to wait until receives a message from the server that lifts up the remote window value again.
     
  30. karmington2

    karmington2

    Joined:
    Jul 30, 2018
    Posts:
    8
    Greetings. Recently upgraded one of our projects to use BestHttp/2, and now I am getting intermittent errors like this with HTTPRequests:

    Code (CSharp):
    1. {"tid":269,"div":"HTTPResponse","msg":"Failed to read Status Line! Retry is disabled, re-throwing exception.","stack":"  at HTTPResponse.Receive (System.Int32 forceReadRawContentLength, System.Boolean readPayloadData, System.Boolean sendUpgradedEvent) [0x000b6] in ...
    Any clues on what might be going wrong? It seems to happen only in Unity Editor ( 2019.3.4f1 ), I have not noticed any problems in actual builds so far. Seems to happen pretty consistently on the first HTTPRequest I try.
     
    Last edited: Feb 16, 2021
  31. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @karmington2 It's probably beacause of changes in the connection pooling behavior. You can lower the HTTPManager.MaxConnectionIdleTime about one sec lower than your server's value, or you can try out different values if you don't have access to the server.
     
    karmington2 likes this.
  32. waldgeist

    waldgeist

    Joined:
    May 6, 2017
    Posts:
    283
    If I send a simple HTTP request in the editor and try to display the response like this:

    Code (CSharp):
    1. void OnRequestFinished(HTTPRequest request, HTTPResponse response) {
    2.   if (response.StatusCode != 200) {
    3.     Debug.Log($"HTTP request error: {response.StatusCode}");
    4.     return;
    5.   }
    6.   Debug.Log(response.DataAsText);
    7. }
    I am getting a HTTP status change error:

    Code (JavaScript):
    1. {"tid":1,"div":"RequestEventHelper","msg":"HandleRequestStateChange Error","ex": [{"msg": "Object reference not set to an instance of an object", "stack": "  at Marble.Locations.Service.StubLocationService.OnRequestFinished (BestHTTP.HTTPRequest request, BestHTTP.HTTPResponse response) [0x00001] in
    This doesn't happen all the times, but quite often and at random. And only if the server is located on my local MacBook (local IP). What may be the reason for this? The response contains a simple JSON text string.
     
    Last edited: Feb 17, 2021
    karmington2 likes this.
  33. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @waldgeist

    First, the response can be null in qute a few cases (see the error handling topic).
    And it could fail for the above mentioned connection pooling. Your remote server probably has different settings than your local one. The plugin tries to negotiate its own values and get what's the server uses, but only a few servers support it, so it have to go with the default values. You can try setting HTTPManager.MaxConnectionIdleTime lower and lower until you find your server's sweet spot.
     
    waldgeist and karmington2 like this.
  34. karmington2

    karmington2

    Joined:
    Jul 30, 2018
    Posts:
    8
    Hmm, I realized I'm also seeing my very similar problem when running against local server! That could be a good clue.
     
    Last edited: Feb 17, 2021
  35. waldgeist

    waldgeist

    Joined:
    May 6, 2017
    Posts:
    283
    Ok, thanks for the info. The thing is that this problem even occurs if the app has just been started, so the connection is "brand-new".
     
  36. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @waldgeist In that case, could you set the plugin's log level and send the produced log to me?
    Code (CSharp):
    1. HTTPManager.Logger.Level = Logger.Loglevels.All;
     
  37. waldgeist

    waldgeist

    Joined:
    May 6, 2017
    Posts:
    283
    Ok, will do. Where can I find the logs once they have been created?
     
  38. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @waldgeist By default it's going to use unity's Debug logging hence going to be written to the Editor.log.
     
  39. gamerko

    gamerko

    Joined:
    Sep 26, 2018
    Posts:
    8
    @BestHTTP
    Hello.

    I have a question about BestHttp.

    When opening and closing a socket multiple times, is there a case where the callback (Close) of a socket that has already disappeared is called?

    In other words, is the order of "open" and "close" guaranteed?
     
  40. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @gamerko

    What events do you subscribed to? "connect" and "disconnect" events should be paired, but when reconnecting they going to be repeated (connect -> disconnect -> reconnect -> connect -> disconnect -> ...).
     
  41. shreee

    shreee

    Joined:
    Aug 31, 2016
    Posts:
    19
    @BestHTTP

    Hello,

    please help me in my case socket.io connect with server in only in editor ..when i build for android or window not connecting with node server..in editor working good
     
  42. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
  43. shreee

    shreee

    Joined:
    Aug 31, 2016
    Posts:
    19

    Attached Files:

  44. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @shreee The log contains a NullReferenceException only:
    Code (CSharp):
    1. 03-11 14:19:21.439 17874 17890 E Unity   : NullReferenceException: Object reference not set to an instance of an object.
    2.  
    3. 03-11 14:19:21.439 17874 17890 E Unity   :   at NetworkManageScript.Awake () [0x00000] in <00000000000000000000000000000000>:0
    This might be relevant to your issue, but there are no logs from the plugin.
     
  45. shreee

    shreee

    Joined:
    Aug 31, 2016
    Posts:
    19
    @BestHTTP

    thank you,

    when i already implement this plugin that time this issue not popping but only last time so am asking you any way solved it. its other plugin merge issue.
     
    Last edited: Mar 11, 2021
  46. gamerko

    gamerko

    Joined:
    Sep 26, 2018
    Posts:
    8
    Hello.

    If the connection is lost or the network changes after calling the Send function, an exception is thrown.

    But in this case, the CallBack set on Send is not called.

    Is there any way to know when an exception is thrown from a "send" function like this?
     
  47. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @gamerko

    "But in this case, the CallBack set on Send is not called."
    I'm not sure what mean here. Could you show your code?
     
  48. gamerko

    gamerko

    Joined:
    Sep 26, 2018
    Posts:
    8

    string uriStr = string.Format("{0}{1}", urlHeader, servicename);
    Uri uri = new Uri(uriStr);

    HTTPRequest req = new HTTPRequest(uri, HTTPMethods.Post, (HTTPRequest originalRequest, HTTPResponse response) =>
    {
    // do not call this function.
    });

    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(json);
    req.Tag = DateTime.Now;
    req.RawData = buffer;
    req.Send();


    It's happening intermittently when changing from IOS to WIFI->LTE.
     
  49. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,634
    @gamerko

    To detect a connection loss with TCP a client must be able to send packets. With HTTP/1.1 (that uses TCP) after the client sent the request it can't send any other data, so it can rely only on the system to detect and propagate connection loss.
    The plugin tries to enable TCP Keep-Alive packets, but that will send packets very infrequently (RFC 1122 declares its default as "at least 2 hours"). You can uncomment lines 489-490 in the TcpClient.cs and try to set different values.
     
  50. yathish9158

    yathish9158

    Joined:
    Apr 24, 2020
    Posts:
    4
    @BestHTTP

    Hey, when the internet fluctuates WebSocket will disconnect and reconnect back. But later it will get disconnect and it keeps on reconnecting and never connects.