Search Unity

Best HTTP Released

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

  1. xpxilom

    xpxilom

    Joined:
    Aug 28, 2014
    Posts:
    30
    How do I do that?

    Code (CSharp):
    1. Uri uri = new Uri("https://graph.facebook.com/"+uid+"/picture?width=9999&height=9999");
    2.  
    3.         HTTPRequest request = new HTTPRequest(uri, (req, resp) =>
    4.             {
    5.                 List<string> names = new List<string>();
    6.                 names = resp.GetHeaderValues("location");
    7.                
    8.                 Debug.Log(names.Count.ToString());
     
  2. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @xpxilom

    A very basic implementation would look like this:
    Code (CSharp):
    1. void FacebookRedirectTest()
    2. {
    3.     HTTPManager.Logger.Level = BestHTTP.Logger.Loglevels.All;
    4.  
    5.     Uri uri = new Uri("https://graph.facebook.com/100009154388931/picture?width=9999&height=9999");
    6.  
    7.     HTTPRequest request = new HTTPRequest(uri, OnFacebookRedirect);
    8.  
    9.     request.MaxRedirects = 0;
    10.     request.Send();
    11. }
    12.  
    13. void OnFacebookRedirect(HTTPRequest req, HTTPResponse resp)
    14. {
    15.     switch (req.State)
    16.     {
    17.         // The request finished without any problem.
    18.         case HTTPRequestStates.Finished:
    19.             if (resp.StatusCode == 302)
    20.             {
    21.                 Debug.Log("Request Finished Successfully! " + resp.Data.Length);
    22.                 var location = resp.GetFirstHeaderValue("location");
    23.                 if (location != null)
    24.                 {
    25.                     var request = new HTTPRequest(new Uri(location), OnFacebookPicture);
    26.                     request.DisableCache = true;
    27.                     request.Send();
    28.                 }
    29.             }
    30.             else // Internal server error?
    31.                 Debug.LogWarning(string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
    32.                                                 resp.StatusCode,
    33.                                                 resp.Message,
    34.                                                 resp.DataAsText));
    35.             break;
    36.  
    37.         // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
    38.         case HTTPRequestStates.Error:
    39.             Debug.LogWarning("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
    40.             break;
    41.  
    42.         // The request aborted, initiated by the user.
    43.         case HTTPRequestStates.Aborted:
    44.             Debug.LogWarning("Request Aborted!");
    45.             break;
    46.  
    47.         // Ceonnecting to the server is timed out.
    48.         case HTTPRequestStates.ConnectionTimedOut:
    49.             Debug.LogError("Connection Timed Out!");
    50.             break;
    51.  
    52.         // The request didn't finished in the given time.
    53.         case HTTPRequestStates.TimedOut:
    54.             Debug.LogError("Processing the request Timed Out!");
    55.             break;
    56.     }
    57. }
    58.  
    59. void OnFacebookPicture(HTTPRequest req, HTTPResponse resp)
    60. {
    61.     switch (req.State)
    62.     {
    63.         // The request finished without any problem.
    64.         case HTTPRequestStates.Finished:
    65.             if (resp.IsSuccess)
    66.             {
    67.                 Debug.Log("Request Finished Successfully! " + resp.Data.Length);
    68.             }
    69.             else // Internal server error?
    70.                 Debug.LogWarning(string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
    71.                                                 resp.StatusCode,
    72.                                                 resp.Message,
    73.                                                 resp.DataAsText));
    74.             break;
    75.  
    76.         // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
    77.         case HTTPRequestStates.Error:
    78.             Debug.LogWarning("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
    79.             break;
    80.  
    81.         // The request aborted, initiated by the user.
    82.         case HTTPRequestStates.Aborted:
    83.             Debug.LogWarning("Request Aborted!");
    84.             break;
    85.  
    86.         // Ceonnecting to the server is timed out.
    87.         case HTTPRequestStates.ConnectionTimedOut:
    88.             Debug.LogError("Connection Timed Out!");
    89.             break;
    90.  
    91.         // The request didn't finished in the given time.
    92.         case HTTPRequestStates.TimedOut:
    93.             Debug.LogError("Processing the request Timed Out!");
    94.             break;
    95.     }
    96. }
    But, it doesn't handle multiple redirects, and other corner cases(other redirection status codes, etc). My recommendation would be to find out why can't get the image by default.
     
  3. ickydime

    ickydime

    Joined:
    Nov 20, 2012
    Posts:
    110
    I bought pro yesterday and am having an issue with UrlEncoded fields in WebGL.

    Here is my setup and the Request helper function just sets the Uri and adds some headers needed to hit Parse's REST Api.

    Code (CSharp):
    1. var request = Request(HTTPMethods.Get, "/login");
    2.  
    3.         HTTPUrlEncodedForm form = new HTTPUrlEncodedForm(); //"application/x-www-form-urlencoded"
    4.         form.AddField("username", username);
    5.         form.AddField("password", password);
    6.         request.SetForm(form);
    7.  
    8.         request.Send();
    This works perfectly in the editor. As soon as I deploy and run in WebGL I get a Finished state but an error in response which states 400-Bad Request Message: Code 201, missing user password.

    Are there any known limitations with using urlencoded fields on WebGL? Or perhaps my setup is wrong?

    Thanks for the help and for putting this code out there.
     
  4. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @ickydime

    First, wouldn't be better to send a form with POST request? The plugin will send it with the form data anyway, but it may generate an error too.

    Second, you don't have to use the HTTPUrlEncodedForm class directly. You should just use the AddField function of the request, and set the form usage on it:
    Code (CSharp):
    1. Uri uri = new Uri("http://httpbin.org/post");
    2.  
    3. HTTPRequest request = new HTTPRequest(uri, HTTPMethods.Post, (req, resp) =>
    4. {
    5.     switch (req.State)
    6.     {
    7.         // The request finished without any problem.
    8.         case HTTPRequestStates.Finished:
    9.             if (resp.IsSuccess)
    10.             {
    11.                 Debug.Log("Request Finished Successfully! Data : " + resp.DataAsText);
    12.             }
    13.             else // Internal server error?
    14.                 Debug.LogWarning(string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
    15.                                                 resp.StatusCode,
    16.                                                 resp.Message,
    17.                                                 resp.DataAsText));
    18.             break;
    19.  
    20.         // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
    21.         case HTTPRequestStates.Error:
    22.             Debug.LogWarning("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
    23.             break;
    24.  
    25.         // The request aborted, initiated by the user.
    26.         case HTTPRequestStates.Aborted:
    27.             Debug.LogWarning("Request Aborted!");
    28.             break;
    29.  
    30.         // Ceonnecting to the server is timed out.
    31.         case HTTPRequestStates.ConnectionTimedOut:
    32.             Debug.LogError("Connection Timed Out!");
    33.             break;
    34.  
    35.         // The request didn't finished in the given time.
    36.         case HTTPRequestStates.TimedOut:
    37.             Debug.LogError("Processing the request Timed Out!");
    38.             break;
    39.     }
    40. });
    41.  
    42. request.AddField("username", "my username");
    43. request.AddField("password", "my unique password");
    44.  
    45. request.FormUsage = BestHTTP.Forms.HTTPFormUsage.UrlEncoded;
    46. request.Send();
     
  5. ickydime

    ickydime

    Joined:
    Nov 20, 2012
    Posts:
    110
    Parse requires a GET on login:

    I tried changing it to a POST just to double check and it responds with a Method not allowed error.

    I made the change to the form data and am getting the same result:
    Code (CSharp):
    1. request.AddField("username", username);
    2.         request.AddField("password", password);
    3.         request.FormUsage = BestHTTP.Forms.HTTPFormUsage.UrlEncoded;
    4.         request.Send();
     
  6. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @ickydime Ok, thanks the curl request too.
    I will check it, but most probably only tomorrow. It getting very late here, sorry.
     
  7. ickydime

    ickydime

    Joined:
    Nov 20, 2012
    Posts:
    110
    @BestHTTP

    No worries! Thank you for the quick responses. I greatly appreciate it. I'll see if I can get more information for you. I am trying to figure out wireshark so I can check the outgoing request.
     
  8. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @ickydime

    Ok, wasn't able to sleep, so played around a bit.
    Signed up to parse, and created a test app. Was able to reproduce your issue.
    Next, crafted a request with a firefox addon, but i got the same error...
    So, checked the cURL help again and it looks like that we done it the wrong way... You have to encode the uasername and password in the url:
    Code (CSharp):
    1. Uri uri = new Uri("https://api.parse.com/1/login?password=p_n7!-e8&username=cooldude6");
    2.  
    3. HTTPRequest request = new HTTPRequest(uri, HTTPMethods.Get, (req, resp) =>
    4. {
    5.     switch (req.State)
    6.     {
    7.         // The request finished without any problem.
    8.         case HTTPRequestStates.Finished:
    9.             if (resp.IsSuccess)
    10.             {
    11.                 Debug.Log("Request Finished Successfully! Data : " + resp.DataAsText);
    12.             }
    13.             else // Internal server error?
    14.                 Debug.LogWarning(string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
    15.                                                 resp.StatusCode,
    16.                                                 resp.Message,
    17.                                                 resp.DataAsText));
    18.             break;
    19.  
    20.         // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
    21.         case HTTPRequestStates.Error:
    22.             Debug.LogWarning("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
    23.             break;
    24.  
    25.         // The request aborted, initiated by the user.
    26.         case HTTPRequestStates.Aborted:
    27.             Debug.LogWarning("Request Aborted!");
    28.             break;
    29.  
    30.         // Ceonnecting to the server is timed out.
    31.         case HTTPRequestStates.ConnectionTimedOut:
    32.             Debug.LogError("Connection Timed Out!");
    33.             break;
    34.  
    35.         // The request didn't finished in the given time.
    36.         case HTTPRequestStates.TimedOut:
    37.             Debug.LogError("Processing the request Timed Out!");
    38.             break;
    39.     }
    40. });
    41.  
    42. request.AddHeader("X-Parse-Application-Id", "XuPNJI9yvsRulYzkPd7Yg9q0hsuWrMnxRFg27wMR");
    43. request.AddHeader("X-Parse-REST-API-Key", "LBiokZPOBEibOUD7YmgXJ83OblmrTW3jLqLcT2eT");
    44. request.AddHeader("X-Parse-Revocable-Session", "1");
    45.  
    46. request.Send();
    Don't know why it's working from the editor, but it should be like this. It worked for me in editor and in webgl too.

    edit: You will have to do some encoding on the username and pasword value to ensure its correctness:
    Code (CSharp):
    1. Uri uri = new Uri(string.Format("https://api.parse.com/1/login?password={0}&username={1}",
    2.                                     WWW.EscapeURL("p_n7!-e8"),
    3.                                     WWW.EscapeURL("cooldude6")));
    (gone sleeping)
     
  9. ickydime

    ickydime

    Joined:
    Nov 20, 2012
    Posts:
    110
    Wow, you just saved me a huge headache. Thank you so much. Well beyond what I expected to find as far as support for a plugin and I just said as much in my review. Let me know if there is anything else I can do to return the favor.

    Cheers
     
  10. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @ickydime Thank you, your review is greatly appreciated and will be enough in return. Thanks.
     
  11. TRsiew

    TRsiew

    Joined:
    Jul 5, 2013
    Posts:
    13
    {"dataset":[{"amount":10.0,"asset":gun,"timer":"10sec","game":"action","user_token":"b4029864-9d90-4702-bf16-a3777b4d3354"}]}

    how can i encode this json array and request send ?
     
  12. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @TRsiew It depends on how your server expect it. You can send it in a form, or as a raw data.

    For the second one you can compose your request something like this:
    Code (CSharp):
    1. Uri uri = new Uri("https://api.myserver.com/");
    2.  
    3. HTTPRequest request = new HTTPRequest(uri, HTTPMethods.Post, (req, resp) =>
    4. {
    5.     switch (req.State)
    6.     {
    7.         // The request finished without any problem.
    8.         case HTTPRequestStates.Finished:
    9.             if (resp.IsSuccess)
    10.             {
    11.                 Debug.Log("Request Finished Successfully! Data : " + resp.DataAsText);
    12.             }
    13.             else // Internal server error?
    14.                 Debug.LogWarning(string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
    15.                                                 resp.StatusCode,
    16.                                                 resp.Message,
    17.                                                 resp.DataAsText));
    18.             break;
    19.  
    20.         // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
    21.         case HTTPRequestStates.Error:
    22.             Debug.LogWarning("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
    23.             break;
    24.  
    25.         // The request aborted, initiated by the user.
    26.         case HTTPRequestStates.Aborted:
    27.             Debug.LogWarning("Request Aborted!");
    28.             break;
    29.  
    30.         // Ceonnecting to the server is timed out.
    31.         case HTTPRequestStates.ConnectionTimedOut:
    32.             Debug.LogError("Connection Timed Out!");
    33.             break;
    34.  
    35.         // The request didn't finished in the given time.
    36.         case HTTPRequestStates.TimedOut:
    37.             Debug.LogError("Processing the request Timed Out!");
    38.             break;
    39.     }
    40. });
    41.  
    42. request.AddHeader("Content-Type", "application/json");
    43.  
    44. string json = @"{""username"":""cooldude6"",""password"":""p_n7!-e8"",""phone"":""415 - 392 - 0202""}";
    45. request.RawData = Encoding.UTF8.GetBytes(json);
    46.        
    47. request.Send();
     
  13. TRsiew

    TRsiew

    Joined:
    Jul 5, 2013
    Posts:
    13
    my server side need to send it include "data-type : jsonp" and HTTPMethods is Get . is it need change it in
    request.AddHeader("Content-Type", "application/jsonp"); ?
     
  14. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @TRsiew
    I think you only have to change the request type to Get.
     
  15. coutlass-supreme

    coutlass-supreme

    Joined:
    Feb 21, 2014
    Posts:
    22
    hi,

    I was wondering how to go about using best http for ftp connections.

    Ive been using native methodsbut i like besthttp's event handlers and other functionalities.

    Is this possible?

    Thank you for your time.
     
  16. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @coutlass.supreme
    FTP is a completely different protocol from HTTP (with its own pitfalls), and it isn't supported now.
     
  17. coutlass-supreme

    coutlass-supreme

    Joined:
    Feb 21, 2014
    Posts:
    22
    thank you for a very fast response!
     
  18. m-garin

    m-garin

    Joined:
    Sep 27, 2015
    Posts:
    4
    1) How can i get information about variables LastHeartbeat and LastPongReceived in BestHTTP.SocketIO specification?
    2) How can i get analogue of variable Network.time (ConnectionStarted - LastHeartbeat + Heandshake.PingInterval????) for interpolate/extrapolate like in example?
     
  19. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @m.garin

    1.) Well, there are some code comments around these fields. The LastHeartbeat is when we sent out the last heartbeat message. LastPongReceived contains the Date&Time when we received the last pong for our ping request. You can make these public to access them outside.

    2.) Well, I think it would be something like this (DateTime.UtcNow - ConnectionStarted). I think after this a higher level interpolation/extrapolation can be implemented.
     
  20. Xorxor

    Xorxor

    Joined:
    Oct 15, 2014
    Posts:
    24
    Please add .DataAsMovieTexture (if it's easy:)
    Thanks!
     
  21. baneand

    baneand

    Joined:
    Dec 3, 2013
    Posts:
    8
    Hello,

    First of all, I have 1.9.4 version of your plugin, just to note that, because that might causing me problems.

    I am using Websockets and WebGL build with my game and when I try to send binary message, I see on server side that it receives an empty array. I am sending message using public void Send(byte[] buffer) method in WebSocket.cs class.

    When I print contents of the buffer after WS_Send_Binary method call like this:

    WS_Send_Binary(this.ImplementationId, buffer, 0, buffer.Length);
    Debug.Log("------- " + "buffer length " + buffer.Length + " " + BitConverter.ToString(buffer));

    I see that everything is OK with the buffer contents, but I still receive empty array on server side.

    Can you check if everything is OK with this method?

    Thanks
     
  22. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @Xorxor Thanks for the suggestion, I will check if It's possible to do with little overhead.
     
  23. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @baneand

    Already fixed it and uploaded a new version to the Asset Store yesterday, but it's not live yet. I would send a link where you can download this new package, but you don't have private messages enabled.
     
  24. baneand

    baneand

    Joined:
    Dec 3, 2013
    Posts:
    8
    I have just marked "Accept conversations from members.." if that was the problem with private messages. Can you try now? Thanks
     
  25. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @baneand Ok, I was able to send a PM now.
     
  26. housecube53

    housecube53

    Joined:
    Jan 27, 2014
    Posts:
    2
    BestHTTP, I'm having an issue with www where once a large response starts to come back, it blocks the UI thread in Unity. Do you know about this and if BestHTTP would not have same issue?
     
  27. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @housecube53

    BestHTTP uses separate threads to download all responses, and will call the callbacks with the result in a unity event(from an Update function). So it will not block any thread.
     
  28. tatata

    tatata

    Joined:
    Jul 11, 2013
    Posts:
    12
    A request to ipv4 address without dns hostname on iOS9 with NAT64 network failed.
    (e.g. `new HTTPRequest(new Uri("http://216.58.220.206")).Send()` failed on iOS9 - NAT64 network)

    This is not a bug, but... UnityEngine.WWW supports that.
    (e.g. `new WWW("http://216.58.220.206")` succeeded on iOS9 - NAT64 network)

    I guess UnityEngine.WWW uses iOS high level networking APIs or uses `getaddrinfo` to convert an ipv4 address to ipv6 one.
    ( https://developer.apple.com/library.../doc/uid/TP40010220-CH213-DontLinkElementID_4 )

    ...Will BestHTTP support that?
     
  29. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @tatata

    Thanks for the report, I will check it out. I can't say an ETA, but I placed it into the top of my TODO list.
     
  30. adamt

    adamt

    Joined:
    Apr 1, 2014
    Posts:
    116
    Hi there. Great library!

    I'm utilizing Best HTTP mainly for WebSockets, currently (maybe more in the future -- are there performance gains to be had using the HTTP API over Unity's own?). One minor thing I noticed is that when I register an event handler to the OnError event, I get an HTTPRequestStates.Aborted error when explicitly calling the WebSocket's Close() method. It seems like this isn't really an error (unless there's something in the WebSockets spec I don't know about, which is entirely possible) and makes me think maybe I'm doing something wrong.

    I'm simply calling ws.close() in the WebSocket's instantiating object's OnDestroy() method, and the "error" is fired. Is this intended behavior?
     
  31. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @adamt

    OnError should be called only when an error occurred. For a Close() call you should receive an OnClosed event when everything when fine.
    However, I seen this type of error in the editor only. In this case, the editor usually closes the tcp connection sooner, causing some bizarre errors.
    I would suggest to ignore it in the editor. If it gets really annoying, I will try to find a workaround however.
     
  32. coutlass-supreme

    coutlass-supreme

    Joined:
    Feb 21, 2014
    Posts:
    22
    Hi mate,

    I was looking for the default timeout on requests. Can you tell me how much time it is?

    Thank you.
     
  33. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @coutlass.supreme

    The RequestTimeout is 60 sec, the ConnectTimeout is 20 sec in the latest releases.
     
  34. coutlass-supreme

    coutlass-supreme

    Joined:
    Feb 21, 2014
    Posts:
    22
    Thanks for the very fast response.
    I think it would be a good addition to the documentation.

    Good day, sir.
     
  35. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
  36. li76168

    li76168

    Joined:
    Sep 7, 2014
    Posts:
    11
    Hello,
    My game was originally used WebSocket-Sharp and run very well.
    But after changing to BestHttp Pro, the stand-alone version is normal, but the web player version is not connected,what the problem is?

    Thanks.
     
  37. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @li76168

    Can you share more information about this problem?
    -Can you see any error displayed?
    -Are you receiving any error subscribing to the OnError or OnErrorDesc events?
    -So WebSocket-Sharp for Unity worked in a WebPlayer build? Have you used any Socket-Policy Service on your target server?
     
  38. fantastisch_

    fantastisch_

    Joined:
    Mar 4, 2015
    Posts:
    26
  39. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
  40. rastinrastini

    rastinrastini

    Joined:
    Jul 8, 2010
    Posts:
    158
    Hi
    - wanna build an racing game that user count maybe around 200k with an master server.
    - these users race with each other in 1vs 1 mode.
    - think from start to end of race each player send only around 10 syncing message(what operated like gear changing) and race end in below of 30 second.
    - when user logged in must not cross side forgery work.
    - cheating and hacking must not work.
    - what solution you offer?(rpc, udp, r-udp, rest, ...)
    - are you mock your library with this high rate?
    - are session work automatically with your library or must handle it myself?
    - what hardware need for this amount of user you think?
    Thankful.
     
  41. fantastisch_

    fantastisch_

    Joined:
    Mar 4, 2015
    Posts:
    26
    That's cool, I can access it as a regular zip archive and go from there. Just wondered, since WWW seems to be usually used to handle it and that doesn't work from threads.
     
  42. rxmarccall

    rxmarccall

    Joined:
    Oct 13, 2011
    Posts:
    353
    @BestHTTP
    At the start of my game each run, I make a HTTP request to get a .json file. It works 90% of the time, but every once and a while it hangs, and produces the following error:



    It appears the hangup is happening with "response" being a null object?

    Code (CSharp):
    1. void GetLatestConfig(HTTPRequest request, HTTPResponse response)
    2.     {
    3.  
    4.         // Parse config json and store information
    5.         configNode = JSON.Parse(response.DataAsText);
    Any idea why this error pops up every so often?
     
  43. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @rastinrastini

    - wanna build an racing game that user count maybe around 200k with an master server.
    It's a concurrent (active/online) players, or registered players? What would be your server setup? One Master and multiple Game servers?

    - think from start to end of race each player send only around 10 syncing message(what operated like gear changing) and race end in below of 30 second.
    With 200K online players it's ~66K request per second average. With 'normal' http requests it would be too much, so i wouldn't recommend an rest setup as it has a very big overhead (big headers, parsing the request, routing the request).

    - cheating and hacking must not work.
    Well, it's a complex topic. You can't say that if you use xy plugin for the networking than you are safe for cheating and hacking. I think, the maximum to avoid these with my plugin if you are using HTTPS.

    - what solution you offer?(rpc, udp, r-udp, rest, ...)
    I would recommend to check out other solutions that are built specifically for these use-cases (Photon, Forge, the new unity networking, etc). Other then these, I would recommend WebSockets for a low-level solution, or Socket.IO for a high level one.

    - are you mock your library with this high rate?
    It is used for real-time multiplayer, but, I think your bottleneck will be your server with this user count.

    - are session work automatically with your library or must handle it myself?
    It depends on what sessions are you required. If you avoid the state-less rest, then you have a persistent connection (session).

    - what hardware need for this amount of user you think?
    Well, if you want it with one server, then you need a very big one. My recommendation would be to partition it for roles(lobby, chat, game server), and do some load balancing. So multiple medium sized lobby servers that will rout the players to little game servers that will handle the race.
     
  44. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @rxmarccall

    I would recommend to use an event handler that will check the request's State:
    Code (CSharp):
    1. void GetLatestConfig(HTTPRequest req, HTTPResponse resp)
    2. {
    3.     switch (req.State)
    4.     {
    5.         // The request finished without any problem.
    6.         case HTTPRequestStates.Finished:
    7.             if (resp.IsSuccess)
    8.             {
    9.                 Debug.Log("Request Finished Successfully! Data : " + resp.DataAsText);
    10.  
    11.                 // Parse config json and store information
    12.                 configNode = JSON.Parse(resp.DataAsText);
    13.  
    14.             }
    15.             else // Internal server error?
    16.                 Debug.LogWarning(string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
    17.                                                 resp.StatusCode,
    18.                                                 resp.Message,
    19.                                                 resp.DataAsText));
    20.             break;
    21.  
    22.         // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
    23.         case HTTPRequestStates.Error:
    24.             Debug.LogWarning("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
    25.             break;
    26.  
    27.         // The request aborted, initiated by the user.
    28.         case HTTPRequestStates.Aborted:
    29.             Debug.LogWarning("Request Aborted!");
    30.             break;
    31.  
    32.         // Ceonnecting to the server is timed out.
    33.         case HTTPRequestStates.ConnectionTimedOut:
    34.             Debug.LogError("Connection Timed Out!");
    35.             break;
    36.  
    37.         // The request didn't finished in the given time.
    38.         case HTTPRequestStates.TimedOut:
    39.             Debug.LogError("Processing the request Timed Out!");
    40.             break;
    41.     }
    42. }
    This way we can more about why the response is null.
     
  45. adamt

    adamt

    Joined:
    Apr 1, 2014
    Posts:
    116
    Hi again.

    I'm having a bit of trouble properly reconnecting my Socket.IO connection on mobile devices. I'm instantiating a standard SocketManager instance, with a delegate defined when the connection is established. That works fine. However, when I suspend my game on my phone, then come back to it a minute or two later, Best HTTP logs this error:

    Code (CSharp):
    1. Err [WebSocketTransport]: OnError: TCP Stream closed unexpectedly by the remote server
    2.     at Org.BouncyCastle.Math.Raw.Nat576.IsOne64 (System.UInt64[] x) [0x00000] in <filename unknown>:0
    3.     at BestHTTP.WebSocket.Frames.WebSocketFrameReader.ReadByte (System.IO.Stream stream) [0x00000] in <filename unknown>:0
    4.     at BestHTTP.WebSocket.Frames.WebSocketFrameReader.Read (System.IO.Stream stream) [0x00000] in <filename unknown>:0
    5.     at BestHTTP.WebSocket.WebSocketResponse.ReceiveThreadFunc (System.Object param) [0x00000] in <filename unknown>:0
    6.     at BestHTTP.SocketIO.Transports.WebSocketTransport:OnError(WebSocket, Exception)
    7.     at BestHTTP.WebSocket.WebSocket:OnInternalRequestCallback(HTTPRequest, HTTPResponse)
    8.     at BestHTTP.HTTPRequest:CallCallback()
    9.     at BestHTTP.ConnectionBase:HandleCallback()
    10.     at BestHTTP.HTTPManager:OnUpdate()
    11.     at Newtonsoft.Json.Utilities.ReflectionDelegateFactory:CreateSet(FieldInfo)
    12.     at Newtonsoft.Json.Utilities.ReflectionDelegateFactory:CreateSet(FieldInfo)
    13.     at Newtonsoft.Json.Utilities.ReflectionDelegateFactory:CreateSet(FieldInfo)
    Even though I get that error, Best HTTP still successfully reconnects to the Socket.IO server. Since I'd rather not have a bunch of errors cluttering up my logs, I added this piece of code to my game when it detects a pause (e.g., when I suspend my game):

    Code (CSharp):
    1. private void OnApplicationPause(bool isPaused)
    2. {
    3.     if(isPaused)
    4.     {
    5.         if(this.ws != null)
    6.         {
    7.             this.ws.Close();
    8.         }
    9.     }
    10.     else
    11.     {
    12.         Debug.LogFormat("Unpaused, WebSockets state: {0}", (this.ws != null ? this.ws.State.ToString() : "(ws is null)"));
    13.  
    14.         if(this.ws != null && this.ws.State == SocketManager.States.Closed)
    15.         {
    16.             Debug.LogFormat("WebSocket connection closed, re-opening");
    17.             this.ws.Open();
    18.         }
    19.     }
    20. }
    The call to this.ws.Open() occurs, and I can see the socket being connected on the server, but Best HTTP no longer fires the callback mapped to the SocketIOEventTypes.Connect event, which is crucial for my presence system to function properly.

    Do you have any suggestions?
     
  46. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @adamt

    The Close() call will remove all namespaces and event subscriptions. It will clean up all resources. You should use it only when you don't want to reuse the manager, or when you will re-subscribe to events.

    So, one solution is to subscribe events again.
    The second one is to call a Close that will not clean up everything:
    Code (CSharp):
    1. (this.ws as IManager).Close(false);
     
    karmington2 likes this.
  47. adamt

    adamt

    Joined:
    Apr 1, 2014
    Posts:
    116
    Thanks, that looks to have worked.

    As an aside, is this an acceptable flow? That is, should I have to call IManager#Close() in OnApplicationPause(), or is there some other way where the auto-reconnection will "just work" without generating these kinds of errors?
     
    Last edited: Jan 13, 2016
  48. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @adamt

    Well, the manager would do the same, basically. It will do a soft-close (Close call with false parameter), then reopen the connection.
     
  49. hkishi

    hkishi

    Joined:
    Jul 29, 2014
    Posts:
    1
  50. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @hkishi

    Definitely!
    My current work is to implement the WebSocket per-message compression. When it will be done, I think I will check Socket.IO's too.