Search Unity

Best HTTP Released

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

  1. cjimison

    cjimison

    Joined:
    Jan 4, 2014
    Posts:
    11
    @BestHTTP

    I just grabbed 1.10.3 and I am now getting a Stream Read error on my websocket connection. If I move back to 1.10.2 it works fine. I have not yet diffed the HTTP code to see what changes could have caused this but I just wanted to check and see if this is a known issue.

    Unity Version: 2017.2.0f3
    OS: Windows 10

    Condition: Running in editor
    Build Platform: PC, Mac & Linux Standalone

    Exception:

    Handled Exception: Read failure
    at System.Net.Sockets.NetworkStream.Read (System.Byte[] buffer, Int32 offset, Int32 size) [0x00000] in <filename unknown>:0
    at System.IO.Stream.ReadByte () [0x00007] in /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.IO/Stream.cs:168
    at BestHTTP.WebSocket.Frames.WebSocketFrameReader.ReadByte (System.IO.Stream stream) [0x00002] in D:\*scrubbed*\Assets\Best HTTP (Pro)\BestHTTP\WebSocket\Frames\WebSocketFrameReader.cs:137
    at BestHTTP.WebSocket.Frames.WebSocketFrameReader.Read (System.IO.Stream stream) [0x00038] in D:\*scrubbed*\Assets\Best HTTP (Pro)\BestHTTP\WebSocket\Frames\WebSocketFrameReader.cs:71
    at BestHTTP.WebSocket.WebSocketResponse.ReceiveThreadFunc (System.Object param) [0x00016] in D:\*scrubbed*\Assets\Best HTTP (Pro)\BestHTTP\WebSocket\WebSocketResponse.cs:415
    0x00000001411B000B (Unity) StackWalker::GetCurrentCallstack
    0x00000001411B288F (Unity) StackWalker::ShowCallstack
    0x000000014108CA30 (Unity) GetStacktrace
    0x0000000140596DA3 (Unity) DebugStringToFile
    0x0000000140597581 (Unity) DebugStringToFile
    0x00000001412E85B2 (Unity) DebugLogHandler_CUSTOM_Internal_Log
    0x00000000153A5DEB (Mono JIT Code) (wrapper managed-to-native) UnityEngine.DebugLogHandler:Internal_Log (UnityEngine.LogType,string,UnityEngine.Object)
    0x00000000153A5CD4 (Mono JIT Code) [DebugLogHandler.cs:9] UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[])
    0x00000000153A55D5 (Mono JIT Code) [Logger.cs:47] UnityEngine.Logger:Log (UnityEngine.LogType,object)
    0x0000000015436F16 (Mono JIT Code) [DebugBindings.gen.cs:168] UnityEngine.Debug:LogWarning (object)
    0x0000000015436360 (Mono JIT Code) [BestWebsocket.cs:362] Playground.Transport.BestWebsocket:OnError (BestHTTP.WebSocket.WebSocket,System.Exception)
    0x000000001542B94C (Mono JIT Code) [WebSocket.cs:330] BestHTTP.WebSocket.WebSocket:OnInternalRequestCallback (BestHTTP.HTTPRequest,BestHTTP.HTTPResponse)
    0x00000000153F726A (Mono JIT Code) [HTTPRequest.cs:1256] BestHTTP.HTTPRequest:CallCallback ()
    0x00000000153F6F99 (Mono JIT Code) [ConnectionBase.cs:173] BestHTTP.ConnectionBase:HandleCallback ()
    0x00000000151F095F (Mono JIT Code) [HTTPManager.cs:611] BestHTTP.HTTPManager:OnUpdate ()
    0x00000000151E87D0 (Mono JIT Code) [HTTPUpdateDelegator.cs:180] BestHTTP.HTTPUpdateDelegator:Update ()
    0x00000000008B7412 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
    0x00007FFD587760FB (mono) [mini.c:4937] mono_jit_runtime_invoke
    0x00007FFD586C8875 (mono) [object.c:2623] mono_runtime_invoke
    0x000000014091D03C (Unity) scripting_method_invoke
    0x00000001409119C3 (Unity) ScriptingInvocation::Invoke
    0x00000001408D3071 (Unity) MonoBehaviour::CallMethodIfAvailable
    0x00000001408DEA8F (Unity) MonoBehaviour::CallUpdateMethod
    0x00000001403A1B66 (Unity) BaseBehaviourManager::CommonUpdate<BehaviourManager>
    0x00000001403A289F (Unity) BehaviourManager::Update
    0x00000001405DB523 (Unity) `InitPlayerLoopCallbacks'::`38'::UpdateScriptRunBehaviourUpdateRegistrator::Forward
    0x00000001405D9CC6 (Unity) PlayerLoop
    0x00000001410B9862 (Unity) PlayerLoopController::UpdateScene
    0x00000001410BADDF (Unity) PlayerLoopController::UpdateSceneIfNeeded
    0x00000001410C4599 (Unity) Application::TickTimer
    0x00000001412CC349 (Unity) MainMessageLoop
    0x00000001412CDC04 (Unity) WinMain
    0x0000000141DE45A8 (Unity) __tmainCRTStartup
    0x00007FFDA11D2774 (KERNEL32) BaseThreadInitThunk
    0x00007FFDA1530D51 (ntdll) RtlUserThreadStart
     
  2. waxx

    waxx

    Joined:
    Apr 1, 2013
    Posts:
    48
    Somehow the SignalR connection doesn't get closed when I stop the editor. Any way to close the connection automatically? It even reconnected me to the server when I wasn't playing the app anymore...
     
  3. BestHTTP

    BestHTTP

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

    Hmm, what limit are you referring to? Can you give a link or a quote about it?

    On 2nd question: Unfortunately the system shuts down the TCP channels, i don't know any way to keep it open.
     
  4. BestHTTP

    BestHTTP

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

    Are you know what websocket server are you connecting to? And about how much time passes when you receive this error?
     
  5. BestHTTP

    BestHTTP

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

    Thanks for the report!.
     
  6. Jribs

    Jribs

    Joined:
    Jun 10, 2014
    Posts:
    154
    @BestHTTP This is the quote I was referring to.
     
  7. BestHTTP

    BestHTTP

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

    I see, thanks.

    The \Assets\Best HTTP (Pro)\BestHTTP\Forms\HTTPFormBase.cs has one constant named LongLength, that you can change to whatever value you feel more convenient.
    When you add a text field using the HTTPRequest's AddField function and that text's length reaches this threashold, it will send the form multipart/form-data encoded.

    As noted in that comment, you can also force the request to use the encoding you choose by setting the HTTPRequest's FormUsage.
     
  8. waxx

    waxx

    Joined:
    Apr 1, 2013
    Posts:
    48
    @BestHTTP Hey. Did you find out what's the issue with SignalR?

    Also - I'd like to automatically reconnect to a signalr server without authentication provider once your authentication fails. (basically reconnect as a guest). How would you implement it?
     
  9. BestHTTP

    BestHTTP

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

    Yes, fixed it.

    On guest authentication: i think it would be the best to create a new connection without an authentication provider. Or, maybe you can use an authentication provider, but generate a username and assign a 'guest' role?
     
  10. waxx

    waxx

    Joined:
    Apr 1, 2013
    Posts:
    48
    Hm, guess simply creating new connection would be the best. Do you recommend using a current instance and calling .Close() and .Open() with a null provider, or creating a new object? Asking because not sure how the object would behave if it was just consumed by GC.

    In terms of the fix: is there going to be an update? Or you can provide me the hotfix? (I got the pro with source code).
     
  11. BestHTTP

    BestHTTP

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

    In this case i would recommend to create a new object.

    Sent a download link to an updated package in a private message.
     
  12. waxx

    waxx

    Joined:
    Apr 1, 2013
    Posts:
    48
    Thanks, I received the package.
    Unfortunately still when exiting application I get the following errors:

    https://i.imgur.com/21Ww28i.png

    sprawling all the way from HTTPUpdateDelegator:OnApplicationQuit(). So far I think it doesn't try to reconnect me in editor at least! So that got fixed.

    Stack trace:

    Err [SignalR Connection]: Request Aborted!
    UnityEngine.Debug:LogError(Object)
    BestHTTP.Logger.DefaultLogger:Error(String, String) (at Assets/3rd Party/Best HTTP (Pro)/BestHTTP/Logger/DefaultLogger.cs:76)
    BestHTTP.SignalR.Connection:BestHTTP.SignalR.IConnection.Error(String) (at Assets/3rd Party/Best HTTP (Pro)/BestHTTP/SignalR/Connection.cs:866)
    BestHTTP.SignalR.Transports.WebSocketTransport:WSocket_OnError(WebSocket, String) (at Assets/3rd Party/Best HTTP (Pro)/BestHTTP/SignalR/Transports/WebSocketTransport.cs:164)
    BestHTTP.WebSocket.WebSocket:OnInternalRequestCallback(HTTPRequest, HTTPResponse) (at Assets/3rd Party/Best HTTP (Pro)/BestHTTP/WebSocket/WebSocket.cs:333)
    BestHTTP.HTTPRequest:CallCallback() (at Assets/3rd Party/Best HTTP (Pro)/BestHTTP/HTTPRequest.cs:1259)
    BestHTTP.ConnectionBase:HandleCallback() (at Assets/3rd Party/Best HTTP (Pro)/BestHTTP/Connections/ConnectionBase.cs:173)
    BestHTTP.HTTPManager:OnUpdate() (at Assets/3rd Party/Best HTTP (Pro)/BestHTTP/HTTPManager.cs:645)
    BestHTTP.HTTPManager:OnQuit() (at Assets/3rd Party/Best HTTP (Pro)/BestHTTP/HTTPManager.cs:775)
    BestHTTP.HTTPUpdateDelegator:OnApplicationQuit() (at Assets/3rd Party/Best HTTP (Pro)/BestHTTP/HTTPUpdateDelegator.cs:247)
     
  13. BestHTTP

    BestHTTP

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

    Keeping the errors was intentional (but it won't call the error callback).
     
  14. waxx

    waxx

    Joined:
    Apr 1, 2013
    Posts:
    48
    I see. Can I disable it somehow though? Like to keep my log clean after app quit.
     
  15. BestHTTP

    BestHTTP

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

    You can disable all logging by setting the plugin's loglevel to None:
    Code (CSharp):
    1. BestHTTP.HTTPManager.Logger.Level = BestHTTP.Logger.Loglevels.None;
    You can set it once in your startup code.

    An alternate way is to write a null logger and assign it to the Logger itself:
    Code (CSharp):
    1. public sealed class NullLogger : BestHTTP.Logger.ILogger
    2. {
    3.     public Loglevels Level { get; set; }
    4.     public string FormatVerbose { get; set; }
    5.     public string FormatInfo { get; set; }
    6.     public string FormatWarn { get; set; }
    7.     public string FormatErr { get; set; }
    8.     public string FormatEx { get; set; }
    9.  
    10.     public NullLogger()
    11.     {
    12.         FormatVerbose = FormatInfo = FormatWarn = FormatErr = FormatEx = string.Empty;
    13.     }
    14.  
    15.     public void Error(string division, string err)
    16.     {}
    17.  
    18.     public void Exception(string division, string msg, Exception ex)
    19.     {}
    20.  
    21.     public void Information(string division, string info)
    22.     {}
    23.  
    24.     public void Verbose(string division, string verb)
    25.     {}
    26.  
    27.     public void Warning(string division, string warn)
    28.     {}
    29. }
    30.  
    31. BestHTTP.HTTPManager.Logger = new NullLogger();
     
  16. waxx

    waxx

    Joined:
    Apr 1, 2013
    Posts:
    48
    Ah yes, I know how to disable the entire logging. Just wondering if I can somehow disable the error on exit myslef.
     
  17. BestHTTP

    BestHTTP

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

    Updated the package, you should be able to download it from the same url I sent.
    It will remove one error logging, and if you want you can remove the second one by commenting it out in the \Assets\Best HTTP (Pro)\BestHTTP\SignalR\Transports\WebSocketTransport.cs at line 161.
     
  18. Cripple

    Cripple

    Joined:
    Aug 16, 2012
    Posts:
    92
    Is there any chance that BestHttp supports TLS 1.2 ? At least for Windows :)

    Cheers
     
  19. BestHTTP

    BestHTTP

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

    It should on all platforms (under WebGL it uses the Browser's XmlHTTPRequest).
    (By default it doesn't use mono's SslStream implementation, instead the plugin comes with BouncyCastle.)
     
  20. waxx

    waxx

    Joined:
    Apr 1, 2013
    Posts:
    48
    Thanks @BestHTTP. Looks like that'll do.
     
  21. Genom

    Genom

    Joined:
    Dec 2, 2014
    Posts:
    86
    hi! anyone tried connecting Signalr Core 2?

    cheers!
     
  22. BestHTTP

    BestHTTP

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

    I tried! :)

    It's a completely different protocol than the previous SignalR versions. I already did a minimal working POC code, but there's a lot of things to design and code.
     
  23. Genom

    Genom

    Joined:
    Dec 2, 2014
    Posts:
    86
    Yep! it used to be something like

    (url + "/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22" + hub + "%22%7D%5D&clientProtocol=1.5&_=1408716619953")

    but now it changed, I am trying to replicate with websocket in the meantime, following self generated javascript, could you share your poc please? it may help for mine : )
     
  24. BestHTTP

    BestHTTP

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

    If you didn't already, you should read these two documents: Hub Protocol and Transport Protocol.

    Connecting with WebSocket is quite straightforward now:
    Code (CSharp):
    1.     internal sealed class WebSocketTransport : ITransport
    2.     {
    3.         public TransportTypes TransportType { get { return TransportTypes.WebSocket; } }
    4.         public TransferModes TransferMode { get { return TransferModes.Binary; } }
    5.         public TransportStates State { get; private set; }
    6.  
    7.         private WebSocket.WebSocket webSocket;
    8.         private HubConnection connection;
    9.  
    10.         public WebSocketTransport(HubConnection con)
    11.         {
    12.             this.connection = con;
    13.             this.State = TransportStates.Initial;
    14.         }
    15.  
    16.         public void StartConnect()
    17.         {
    18.             if (this.webSocket == null)
    19.                 this.webSocket = new WebSocket.WebSocket(this.connection.Uri);
    20.             this.webSocket.Open();
    21.             this.webSocket.OnOpen += OnOpen;
    22.             this.webSocket.OnMessage += OnMessage;
    23.             this.webSocket.OnBinary += OnBinary;
    24.             this.webSocket.OnErrorDesc += OnError;
    25.             this.webSocket.OnClosed += OnClosed;
    26.             this.State = TransportStates.Connecting;
    27.         }
    28.  
    29.         private void OnOpen(WebSocket.WebSocket webSocket)
    30.         {
    31.             this.webSocket.Send(string.Format("{{'protocol':'{0}'}}", this.connection.Encoder.Name));
    32.  
    33.             this.State = TransportStates.Connected;
    34.             this.connection.TransportConnected(this);
    35.         }
    36.  
    37.         private void OnMessage(WebSocket.WebSocket webSocket, string message)
    38.         {
    39.         }
    40.  
    41.         private void OnBinary(WebSocket.WebSocket webSocket, byte[] data)
    42.         {
    43.         }
    44.  
    45.         private void OnError(WebSocket.WebSocket webSocket, string reason)
    46.         {
    47.             this.State = TransportStates.Closed;
    48.             this.connection.TransportClosed(this);
    49.         }
    50.  
    51.         private void OnClosed(WebSocket.WebSocket webSocket, ushort code, string message)
    52.         {
    53.             this.webSocket = null;
    54.             this.State = TransportStates.Closed;
    55.             this.connection.TransportClosed(this);
    56.         }
    57.  
    58.         public void StartClose()
    59.         {
    60.             if (this.webSocket != null)
    61.                 this.webSocket.Close();
    62.             this.State = TransportStates.Closing;
    63.         }
    64.     }
    Edit: i wrote this code about more than a month ago, and the protocol is still under development, so you really should read the above documents as this code might not work now.
     
  25. Genom

    Genom

    Joined:
    Dec 2, 2014
    Posts:
    86
    Hello again! thanks for the info. I'm trying to negotiate the connection with this

    var request = new HTTPRequest(new Uri("http://localhost:50420/MyHub"), HTTPMethods.Post, (req, response)=>
    {
    var lolo = response;
    });

    var negotiation = "\"{\"connectionId\":\"" + Guid.NewGuid() + "\", \"availableTransports\":[\"WebSockets\"]}\"";


    request.AddHeader("Content-Type", "application/json");
    request.RawData = Encoding.UTF8.GetBytes(negotiation);
    request.Send();


    but it gives "Bad Requst: Connection ID required" mmm I'm not sure what's wrong...

    And I cannot see the post in fiddler (while the javascript version yes)

    [Edit2]
    Further info:

    this works written in Fiddler
    OPTIONS http://localhost:50420/NodelingHub HTTP/1.1
    Host: localhost:50420
    Connection: keep-alive
    Pragma: no-cache
    Cache-Control: no-cache
    Origin: http://localhost:50420
    X-Requested-With: XMLHttpRequest
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
    Accept: */*
    Referer: http://localhost:50420/
    Accept-Encoding: gzip, deflate, br
    Accept-Language: es-ES,es;q=0.9

    but if I use POST it doesn't


    [Edit 3]
    I hadn't the last version of Besthttp,the last one has the OPTIONS verb and now it works, I have the connection Id! : ) next steps is opening the websocket
     
    Last edited: Nov 30, 2017
  26. BestHTTP

    BestHTTP

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

    Yeah, the OPTIONS are there because of SignalR Core. But, one thing that i don't understand is why are you not connecting straight with websockets?

     
    Last edited: Dec 1, 2017
  27. Genom

    Genom

    Joined:
    Dec 2, 2014
    Posts:
    86
    Hi the reason why is because I was following an implementation in Unity using Websocketsharp where you first get the token and then you open the ws for the full duplex. Right now I have (the code is a mess, once is working I'll refactor it):

    public bool Init(string url, string hub)
    {
    this.url = url;
    this.hub = hub;
    this.m_result = null;
    _actionMap = new Dictionary<string, UnTypedActionContainer>();

    try
    {
    var request = new HTTPRequest(new Uri("http://localhost:50420/NodelingHub"), HTTPMethods.Options, (req, response)=>
    {
    if (response.Message == "OK")
    {
    _connectionToken = response.DataAsText.Substring(17, 36);

    Open();
    }
    });

    request.AddHeader("Connection", "keep-alive");
    request.AddHeader("Pragma", "no-cache");
    request.AddHeader("Cache-Control", "no-cache");
    request.AddHeader("Accept", "*/*");
    request.AddHeader("Accept-Encoding", "gzip, deflate, br");
    request.Send();


    return true;
    }
    catch (Exception e1)
    {
    return false;
    }
    }


    public void Open()
    {
    var r1 = new Random(DateTime.Now.Millisecond);
    var protocoledAddress = url.ToLower().Replace("https", "ws").Replace("http", "ws");
    var address = protocoledAddress + "/NodelingHub?id=" + _connectionToken;
    if (_ws == null)
    {
    _ws = new WebSocket(address); // web socket sharp, change for BestHTTP
    }
    else
    {
    _ws = new WebSocket(address);// web socket sharp, change for BestHTTP
    }
    AttachAndConnect();
    }

    Once I understand how to do it all only with WS I'll be happy to use the full duplex for the whole process : )
     
  28. sviper_maxim

    sviper_maxim

    Joined:
    Jun 15, 2017
    Posts:
    1
    Hi,
    I got this exception on iOS when I put the App in the background while a Request was going on. As soon as I reopened the App I got the following exception:

    BestHttp Version: 1.10.2
    iPhone: iPhone 7 (iOS 10)

    Code (CSharp):
    1. SocketException: The socket has been shut down
    2.  
    3. System.Net.Sockets.Socket.Send (System.Byte[] buf, Int32 offset, Int32 size, SocketFlags flags)
    4. System.Net.Sockets.NetworkStream.Write (System.Byte[] buffer, Int32 offset, Int32 size)
    5. Org.BouncyCastle.Crypto.Tls.RecordStream.WriteRecord (Byte type, System.Byte[] plaintext, Int32 plaintextOffset, Int32 plaintextLength)
    6. Org.BouncyCastle.Crypto.Tls.TlsProtocol.SafeWriteRecord (Byte type, System.Byte[] buf, Int32 offset, Int32 len)
    7. Org.BouncyCastle.Crypto.Tls.TlsProtocol.FailWithError (Byte alertLevel, Byte alertDescription, System.String message, System.Exception cause)
    8. Org.BouncyCastle.Crypto.Tls.TlsStream.Close ()
    9. BestHTTP.HTTPManager.OnUpdate ()
    10. Rethrow as IOException: Write failure
    11. System.Net.Sockets.NetworkStream.Write (System.Byte[] buffer, Int32 offset, Int32 size)
    12. Org.BouncyCastle.Crypto.Tls.RecordStream.WriteRecord (Byte type, System.Byte[] plaintext, Int32 plaintextOffset, Int32 plaintextLength)
    13. Org.BouncyCastle.Crypto.Tls.TlsProtocol.SafeWriteRecord (Byte type, System.Byte[] buf, Int32 offset, Int32 len)
    14. Org.BouncyCastle.Crypto.Tls.TlsProtocol.FailWithError (Byte alertLevel, Byte alertDescription, System.String message, System.Exception cause)
    15. Org.BouncyCastle.Crypto.Tls.TlsStream.Close ()
    16. BestHTTP.HTTPManager.OnUpdate ()
    and

    Code (CSharp):
    1. Ex [HTTPRequest]: CallCallback - Message: 1: A null value was found where an object instance was required. at BestHTTP.HTTPRequest.CallCallback () [0x00000] in <filename unknown>:0
    2. at BestHTTP.ConnectionBase.HandleCallback () [0x00000] in <filename unknown>:0
    3. at BestHTTP.HTTPManager.OnUpdate () [0x00000] in <filename unknown>:0 StackTrace: at BestHTTP.HTTPRequest.CallCallback () [0x00000] in <filename unknown>:0
    4. at BestHTTP.ConnectionBase.HandleCallback () [0x00000] in <filename unknown>:0
    5. at BestHTTP.HTTPManager.OnUpdate () [0x00000] in <filename unknown>:0
    6.  
    7. BestHTTP.Logger.DefaultLogger:Exception(String, String, Exception)
    8. BestHTTP.ConnectionBase:HandleCallback()
    9. BestHTTP.HTTPManager:OnUpdate()
     
  29. BestHTTP

    BestHTTP

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

    You can connect with WebSocket just by opening a websocket connection to the original url (ws://localhost:50420/NodelingHub) and send the {'protocol': 'json'} json string back to the server. After this step it's considered as an open connection and both the server and client can send messages.
     
  30. BestHTTP

    BestHTTP

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

    Under mobile OSs the underlying system will close the application's tcp connections, and suspends all of its threads when it goes to the background. It has a wait time as the user might switch back to the app in a short time.
    When the user switch to the app again, its threads will run again, and will detect the tcp connection closures (read or write operations will fail).
     
  31. Genom

    Genom

    Joined:
    Dec 2, 2014
    Posts:
    86
    Hi again (again)

    My last version of code, still connection close, I'm not sure where and how I have to send the protocol : json message

    Code (CSharp):
    1. public void Open()
    2.         {
    3.             var address = "ws://localhost:50420/MyHub";      
    4.             _ws = new WebSocket(new Uri(address));
    5.  
    6.             AttachAndConnect();
    7.         }
    8.         private void AttachAndConnect()
    9.         {
    10.             _ws.OnOpen += (ws)=>
    11.             {
    12.                 _ws.Send(string.Format("{{'protocol':'json'}}"));
    13.                 var a = ws;
    14.             };
    15.  
    16.             _ws.OnMessage += (ws, message) =>
    17.             {
    18.                 var a = ws;
    19.                 var m = message;
    20.             };
    21.  
    22.             _ws.OnClosed += (ws, code, message) =>
    23.             {
    24.                 var a = ws;
    25.                 var c = code;
    26.                 var m = message;
    27.             };
    28.  
    29.             _ws.OnError += (ws, ex) =>
    30.             {
    31.                 var a = ws;
    32.                 var m = ex;
    33.             };
    34.  
    35.             _ws.Open();
    36.         }
    now it gives a 1011 error, any idea?

    pd: server error:

    Microsoft.AspNetCore.Sockets.ConnectionManager:Error: 12/01/2017 18:42:31: ConnectionId b92ecdd2-3b3e-40b9-b084-ae3d41a4c7f2: Failed disposing connection.

    System.FormatException: Unable to parse payload as a negotiation message.
    at Microsoft.AspNetCore.SignalR.Internal.Protocol.NegotiationProtocol.TryParseMessage(ReadOnlyBuffer`1 input, NegotiationMessage& negotiationMessage)
    at Microsoft.AspNetCore.SignalR.HubEndPoint`1.<ProcessNegotiate>d__12.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.AspNetCore.SignalR.HubEndPoint`1.<OnConnectedAsync>d__11.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.AspNetCore.Sockets.HttpConnectionDispatcher.<ExecuteApplication>d__7.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.AspNetCore.Sockets.DefaultConnectionContext.<WaitOnTasks>d__56.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.AspNetCore.Sockets.DefaultConnectionContext.<DisposeAsync>d__55.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at Microsoft.AspNetCore.Sockets.ConnectionManager.<DisposeAndRemoveAsync>d__14.MoveNext()
     
    Last edited: Dec 1, 2017
  32. cong91

    cong91

    Joined:
    May 31, 2013
    Posts:
    5
    I have problem when build my game for WebGL.
    I use BestHTTP PRO for connection socket.io client with server.
    My case is open game in web brower. After i switch to other tab. after 2 minutes i switch back tab my game. In this time SocketManager. States is Disconnect. It not reconnect with this case. i don't know why.
    This is my code connection socket
     
  33. mikelaurence

    mikelaurence

    Joined:
    Oct 1, 2013
    Posts:
    11
    Hi, great library, thank you! I just started using the Websockets functionality, and I'm wondering if Nagle's algorithm (e.g. TCP No Delay) is enabled/disabled, and if that is configurable? (Both in normal builds and in WebGL). Or maybe Nagle isn't a thing in Websockets at all -- the Internet has been giving me conflicting information on that front.

    Thanks!
     
  34. BestHTTP

    BestHTTP

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

    Forgot about the record separator that must be appended to every json payload.

    You can send it like this:
    Code (CSharp):
    1. private void OnOpen(WebSocket.WebSocket webSocket)
    2. {
    3.     string json = "{'protocol':'json'}";
    4.     int len = System.Text.Encoding.UTF8.GetByteCount(json);
    5.  
    6.     byte[] buffer = new byte[len + 1];
    7.  
    8.     System.Text.Encoding.UTF8.GetBytes(json, 0, json.Length, buffer, 0);
    9.  
    10.     buffer[len] = 0x1e;
    11.     this.webSocket.Send(buffer);
    12.  
    13.     this.State = TransportStates.Connected;
    14.     this.connection.TransportConnected(this);
    15. }
     
    Last edited: Dec 9, 2017
  35. BestHTTP

    BestHTTP

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

    What browser are you using?
     
  36. BestHTTP

    BestHTTP

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

    You set the TryToMinimizeTCPLatency property to True on the websocket's internal request. This will work under non-WebGL builds, as browsers not let set low-level properties like this (however it's on by default in brwosers). This will be true be default for WebSocket requests in the next update.

    Code (CSharp):
    1. #if !UNITY_WEBGL || UNITY_EDITOR
    2.     webSocket.InternalRequest.TryToMinimizeTCPLatency = true;
    3. #endif
     
  37. OlivierPons

    OlivierPons

    Joined:
    Sep 20, 2014
    Posts:
    28
    Hi, just a question that may have a fast answer: is there a clean way to add parameters to the URL?
    I'm doing something like

    Code (CSharp):
    1.         new HTTPRequest(
    2.             new Uri(baseURL + _urlGetState + "?game=" + game),
    3.             HTTPMethods.Get, AjaxStateGetFinished
    4.         ).Send();
    But I guess there's a cleaner way, something like (my code doesn't work, it's just a wild guess):

    Code (CSharp):
    1. new Uri(baseURL + _urlGetState, new Query({"game": game})
    (and by the way the new version still has the warnings
    Assets/Scripts/BestHTTP/HTTPUpdateDelegator.cs(87,51): warning CS0618: `UnityEditor.EditorApplication.playmodeStateChanged' is obsolete: `Use EditorApplication.playModeStateChanged and/or EditorApplication.pauseStateChanged')
     
  38. BestHTTP

    BestHTTP

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

    As far as i know, there's no easy to use implementation in the current mono framework. There's a QueryBuilder, but it's equally painful to use for queries.

    The plugin uses string additions if there's only a few parameters, for longer ones it uses the QueryBuilder for the base url, and a StringBuilder for the query part.


    What version of the plugin and Unity you have? The current - v1.10.3 - should fix it under 2017.2 (or newer).
     
  39. OlivierPons

    OlivierPons

    Joined:
    Sep 20, 2014
    Posts:
    28
    Hi,
    You're right, I've downloaded the latest version and all warnings are gone, very good job!
    As for the QueryBuilder, this is a burning shame that Microsoft, with so many people in that company, still doesn't have an easy class to handle parameters in the Urls... May I ask you the name of the file where you build you queries?
    Thank you for your answer! Very good support!
     
  40. Genom

    Genom

    Joined:
    Dec 2, 2014
    Posts:
    86
    it works!! great, thanks for the help : ))
     
  41. GLeBaTi

    GLeBaTi

    Joined:
    Jan 12, 2013
    Posts:
    54
    @BestHTTP
    Hello. Does this asset support https certificate validation in WebGL?
     
  42. MadByteLabs

    MadByteLabs

    Joined:
    May 29, 2011
    Posts:
    18
    Hi, tell me pls, can I use BestHTTP in editor mode?
     
  43. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    @BestHTTP is there any way of print out what gets sent to the server?

    I was trying to set up a simple GET request using AddFields:

    HTTPRequest request = new HTTPRequest(new Uri(URL), OnRequestFinished);

    request.AddField("access_token", access_token);
    request.AddField("api_key", api_key);
    request.AddField("include[]", include);

    However it seems to do what I was expecting i.e. build up a request like
    "URL?access_token=value&api_key=value&include[]=value"

    Is this not the way it was intended to be used? i.e. is AddFields only for POST ?

    thanks

    Nalin
     
  44. BestHTTP

    BestHTTP

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

    Well, you can't configure it or write your own. But because the plugin must use the underlying browser's XmlHTTPRequest implementation, it will validate it.
     
  45. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
  46. BestHTTP

    BestHTTP

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

    The plugin will send the field in the request's body as its payload. The plugin will not alter the uri in any way, you have to construct the proper uri before you pass it to the HTTPRequest's constructor:
    Code (CSharp):
    1. string constructedURL = url + string.Format("?access_token={0}&api_key={1}&include[]={2}",
    2.                                                 Uri.EscapeUriString(access_token),
    3.                                                 Uri.EscapeUriString(api_key),
    4.                                                 Uri.EscapeUriString(includes));
    5. HTTPRequest request = new HTTPRequest(new Uri(constructedURL), onFinished);
     
  47. voncarp

    voncarp

    Joined:
    Jan 3, 2012
    Posts:
    187
    How do you get the response.Data? I have been testing various attempts of just sending messages to the server and receiving a response.

    In the following code I am sending a byte array to the server. The server receives it successfully and I included the code with all my debug variables as well:

    Code (CSharp):
    1. MemoryStream stream = new MemoryStream ();
    2.         BinaryWriter writer = new BinaryWriter (stream);
    3.         writer.Write (inttosend);
    4.         byte[] stuff = stream.ToArray ();
    5.         Debug.Log (stuff.Length);
    6.          writer.Close ();
    7.  
    8.         stream = new MemoryStream ();
    9.         writer = new BinaryWriter (stream);
    10.         writer.Write (otherint);
    11.         writer.Write (stuff.Length);
    12.         writer.Write (stuff);
    13.         byte[] sendstuff = stream.ToArray ();
    14.         Debug.Log (sendstuff.Length);
    15.         writer.Close ();
    16.  
    17.         string debugString = Convert.ToBase64String (sendstuff);
    18.         Debug.Log (debugString);
    19.  
    20.         request = new HTTPRequest(new Uri(bytearraySend), HTTPMethods.Post, OnRequestFinishedBytes);
    21.          request.RawData = sendstuff;
    22.           request.Send ();
    23.         stream = new MemoryStream(sendstuff);
    24.         BinaryReader reader = new BinaryReader(stream);
    25.         int x = reader.ReadInt32 ();
    26.         int numberofbytes = reader.ReadInt32 ();
    27.         byte[] receivedArray = reader.ReadBytes(numberofbytes);
    28.  
    29.         MemoryStream stream2 = new MemoryStream (receivedArray);
    30.         BinaryReader reader2 = new BinaryReader (stream2);
    31.         int finalInt = reader2.ReadInt32 ();
    32.         Debug.Log (x + " " + finalInt);
    And from the server I just bounce it back:

    Code (CSharp):
    1. byte[] bytearray = await req.Content.ReadAsByteArrayAsync();
    2.  
    3.               return req.CreateResponse(HttpStatusCode.OK, bytearray);
    4.  
    In this code I receive a response from the server

    Code (CSharp):
    1.     void OnRequestFinishedBytes(HTTPRequest request, HTTPResponse response)
    2.     {
    3.         Debug.Log("OnRequestFinishedBytes: " + response.DataAsText);
    4.         string stringToCut = response.DataAsText;
    5.          Debug.Log(response.Data.Length);
    6.         byte [] dataStuff = response.Data;
    7.         string thatWorks = stringToCut.Remove(0, 1);
    8.         thatWorks = thatWorks.Substring(0, thatWorks.Length-1);
    9.         byte[] byteArraryThatWorks = Convert.FromBase64String (thatWorks);
    10.  
    11.         string debugString = Convert.ToBase64String (response.Data);
    12.         Debug.Log (debugString);
    13.  
    14.         MemoryStream stream = new MemoryStream(byteArraryThatWorks);
    15.         BinaryReader reader = new BinaryReader(stream);
    16.         int x = reader.ReadInt32 ();
    17.         int numberofbytes = reader.ReadInt32 ();
    18.         byte[] receivedArray = reader.ReadBytes(numberofbytes);
    19.  
    20.         MemoryStream stream2 = new MemoryStream (receivedArray);
    21.         BinaryReader reader2 = new BinaryReader (stream2);
    22.         int finalInt = reader2.ReadInt32 ();
    23.         Debug.Log (x + " " + finalInt);
    24.     }
    To get it to work successfully I have to cut the quotation " from the strings from the response.DataAsText and Convert.ToBase64String it. Seems excessive. I would like to just get the byte [] from the response.Data and work from there . Would you have some advice on what I need to do?

    Does it make sense? I am just trying to send a byte array to the server and return the same byte array to test some of BestHTTP functionality.
     
  48. BestHTTP

    BestHTTP

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

    The response's Data is the byte[] that holds all downloaded data from the server. DataAsTest is just a shortcut to convert Data to an utf8 string. So if you don't want, you don't have to use DataAsText, you have access to the raw byte array.

    You can use a proxy (like Charles) to see what the plugin sends out and receives back from the server:
    Code (CSharp):
    1. BestHTTP.HTTPManager.Proxy = new BestHTTP.HTTPProxy(new Uri("http://localhost:8888"), null, true);
     
  49. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    @BestHTTP
    I'm doing some HTTPRequest to receive some data. Based on user interaction I have to do a new request.
    Everything works fine when I wait for the request to complete before to start a new one.
    So to allow the execution of a new request directly after the first one, if the request state < Finished, I call the Abort method of the request object before the new request.
    The system works, but I keep getting a warning in the console: Failed to read Status Line! Retry is disabled
    Please let me know if I should do something different.

    BestHTTP Pro v. 1.10.3 - Unity 2017.2.0f3 - on macOS Sierra 10.12.6

    W [HTTPResponse]: http://myurl/GetTables - Failed to read Status Line! Retry is disabled, re-throwing exception.
    UnityEngine.Debug:LogWarning(Object)
    BestHTTP.Logger.DefaultLogger:Warning(String, String) (at Assets/Plugins/Best HTTP (Pro)/BestHTTP/Logger/DefaultLogger.cs:63)
    BestHTTP.HTTPResponse:Receive(Int32, Boolean) (at Assets/Plugins/Best HTTP (Pro)/BestHTTP/HTTPResponse.cs:220)
    BestHTTP.HTTPConnection:Receive() (at Assets/Plugins/Best HTTP (Pro)/BestHTTP/HTTPConnection.cs:661)
    BestHTTP.HTTPConnection:ThreadFunc(Object) (at Assets/Plugins/Best HTTP (Pro)/BestHTTP/HTTPConnection.cs:230)
    System.Threading._ThreadPoolWaitCallback: PerformWaitCallback()
     
  50. mcmorry

    mcmorry

    Joined:
    Dec 2, 2012
    Posts:
    580
    @BestHTTP
    I have a question about the IsKeepAlive flag of the HTTPRequest.
    Is it consuming server side resources when is enabled? If so, there is a way to "close" the connection once I know that I don't have to execute new requests for a while?