sta / websocket-sharp

A C# implementation of the WebSocket protocol client and server
http://sta.github.io/websocket-sharp
MIT License
5.73k stars 1.66k forks source link

Issue with fast reconnection... #72

Open CornCakePie opened 10 years ago

CornCakePie commented 10 years ago

If I connect to my application for the first time, it will properly connect to the socket and listen to it.

However if I connect, close the socket, close my application and then try to connect again it gets stuck at this part:

20/08/2014 16:52:41|Debug|WebSocket.sendHttpRequest|
A request to the server:
    GET /complete?s=3
                HTTP/1.1

                User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0

                Upgrade: websocket
                Connection: Upgrade
                Host: chat.domain.com
                Origin: http://chat.domain.com
                Sec-WebSocket-Key: Xj/iRVe0qIDcCRxEewkd+A==

                Sec-WebSocket-Extensions: permessage-deflate

                Sec-WebSocket-Version: 13

20/08/2014 16:52:41|Debug|WebSocket.sendHttpRequest|
A response to this request: HTTP/1.1 
                101 Switching Protocols
                Upgrade: websocket
                Connection: Upgrade
                Sec-WebSocket-Accept: iHzCwoe416EVEiQ7s2KoPFQhk6Q=

And receive no data regardless of amount of time I let the application open. Then I have to close the application wait a few seconds before starting it again so that it properly connects.

This is the latest version available on git and the only change I ever made was hardcoded a different user agent.

Since it gives me no information about what is going on in this case the websocket will just remain there so I can't use "Using (var ws....)" as I need to close that socket if the OnMessage event is never trigged.

It does trigger the OnOpen event but that is all it does.

So I have to have it like this on my project:

socket = new WebSocket(Url);
socket.OnMessage += (senter, e) => ReceiveData(e.Data);
socket.OnClose += (sender, e) => Reconnect(e.Code, e.Reason);
socket.Log.Level = LogLevel.Trace;
socket.Log.File = Path.Combine(logFolder, "websocket.log");
socket.Compression = CompressionMethod.Deflate;
socket.Origin = origin;
socket.ConnectAsync();

So that I am able to perform:

socket.Close();

But regardless of closing the socket, I can't reconnect to it again not instantiate a new socket as keeps giving me the other errors I have early reported as different issues, as they are.

sta commented 10 years ago

Hmm,,, could you show me your Reconnect(code, reason) code?

And also i tested reconnect on OnClose event with Example, and it works unless main thread closes.

CornCakePie commented 10 years ago

Yes my reconnect is on the OnClose event.

Socket.OnClose += (sender, e) => Reconnect(e.Code, e.Reason);

Then I have tried simple reconnect like this:

void Reconnect(ushort code, string error)
{
    if (code as CloseStatusCode != CloseStatusCode.Normal)
    {
        socket.ConnectAsync();
    }
}

Tried to completely create a new one:

void Reconnect(ushort code, string error)
{
    socket = new WebSocket(Url);
    socket.OnMessage += (senter, e) => ReceiveData(e.Data);
    socket.OnClose += (sender, e) => Reconnect(e.Code, e.Reason);
    socket.Log.Level = LogLevel.Trace;
    socket.Log.File = Path.Combine(logFolder, "websocket.log");
    socket.Compression = CompressionMethod.Deflate;
    socket.Origin = origin;
    socket.ConnectAsync();
}

Neither of the above worked to reconnect.

Just for the records I've tested this by simple unplugging my network device and reconnecting it after awhile, to emulate a internet disconnection, after the internet was back it couldn't reconnect at all.

sta commented 10 years ago

Does the following make a difference?

void Reconnect(ushort code, string error)
{
    if (code as CloseStatusCode != CloseStatusCode.Normal)
    {
        socket.Connect();

        // Block on this thread for test, e.g. :
        Console.ReadKey (true);
    }
}

How (which timing) do you call that socket.Close() method? It seems that your app closes soon after that method is called.

CornCakePie commented 10 years ago

It gives me the error:

Fatal|WebSocket.processException|WebSocketSharp.WebSocketException: The header part of a frame cannot be read from the data source.
                             at WebSocketSharp.WebSocketFrame+<>c__DisplayClassd.<ParseAsync>b__c (System.Byte[] header) [0x00043] in d:\Visual Studio 2010\Projects\websocket-sharp\WebSocketFrame.cs:631 
                             at WebSocketSharp.Ext+<>c__DisplayClass6.<ReadBytesAsync>b__5 (IAsyncResult ar) [0x00056] in d:\Visual Studio 2010\Projects\websocket-sharp\Ext.cs:626

And then just hold up because of the Console.ReadKey...

socket.Close() is only called when the application is closing and only if the socket was not already closed for whatever reason.

So you're saying that the socket remains alive because when the socket is disconnected it tries to reconnect to fast or when I am closing the application it calls socket.close() and closes the application too fast and that I would need something like:

while (socket != null && socket.ReadyState != WebSocketState.Closed)
{
    Console.WriteLine("Waiting for socket to completely close itself...");
    Thread.Sleep(500);
}
sta commented 10 years ago

And then just hold up because of the Console.ReadKey...

It's an example. Plz use correct function to block for your app.

So,

socket.Close() is only called when the application is closing and only if the socket was not already closed for whatever reason.

Hmm? If so, for what do you reconnect (despite your app is closing)?

...
socket.Close(); // Wait until OnClose has finished, in that case, re-connection has been established.

// Do you have any process to stop your app closing after socket.Close() is called?
// If the following steps do nothing to stop your app closing, that re-connection aborts (without closing connection correctly).
...

Please organize your app's scenario more.

CornCakePie commented 10 years ago

There are several scenarios other than manually using socket.close, that will make your socket close, for instance:

And several other socket events that could potentially close your socket.

So basically what I am doing is, having the reconnect function work if any event not a normal close of the socket happens, that is the only time it uses the Reconnect function.

And one simple way I found to test whether it was working or not was to unplug my network device and plug it back in after the socket is closed.

However as I early mentioned I keep getting that error as if the socket is completely unusable as if it was never disposed of when closed.

sta commented 10 years ago

Perhaps, do you think that socket.Close() closes the connection with CloseStatusCode.Normal?

If so, you should use the following.

socket.Close(CloseStatusCode.Normal);
CornCakePie commented 10 years ago

Like I have previously stated this is not a issue when I close the application as I do use Normal enum when closing the socket to leave the application.

It happens when the socket is closed while the application is running as I have early mentioned if you unplug your internet(given its not a local server), the application will still be running and it will eventually close the socket and trigger the OnClose event which in turn will trigger the Reconnect event.

sta commented 10 years ago

Does the latest and the following make a difference?

void Reconnect(ushort code, string error)
{
    if (code != (ushort) CloseStatusCode.Normal)
    {
        //Thread.Sleep(5000); // If necessary 
        socket.ConnectAsync();
    }
}
chauhan1009 commented 10 years ago

I am working on chat app using xmpp framework. I am facing connection issue on 3G network when network goes off or i put the device on airplane mode the application does not connect again it try to reconnect but connection never goes successful. I had tried all the options mention in the post buy unfortunately none of them is working in my case.

the application is working fine on WiFi network automatically reconnect on network failure, when network come again.

Kindly help me out to fix the reconnection issue on 3G network. Looking for kind help

Regards, Chauhan

sta commented 10 years ago

@chauhan1009 Do you mean that your device cannot reconnect after a time span, on that 3G network (despite it came back to be available)?

chauhan1009 commented 10 years ago

My device working fine on other application like whatsup, wechat and if network has gone or airplane mode and network received again reconnect immediately but in this case my application does't Reconnect immediately. it take long time(5 to 10 minutes) after disconnect network or airplane mode when reconnect again.

sta commented 10 years ago

@chauhan1009 Do you use a mobile device? (Or other?) Plz describe your environment more (e.g. OS, software tools to develop your apps, etc).

And, on your 3G network

  1. Start your app and connect to the server -> do something -> disconnect from server and close your app Does it work?
  2. 1 -> your network fails -> your network recovers -> 1 Does it work?
chauhan1009 commented 10 years ago

Yes, I am using mobile device(iPhone 5) and using iOS 7. I am using 3G network, xCode 5.1.1 and xmppframework.

sta commented 10 years ago

@chauhan1009 Hmm? Do you mean your app is written in Objective-C?

chauhan1009 commented 10 years ago

Yes, My app is written in Objective-C

sta commented 10 years ago

@chauhan1009 How do you use this websocket-sharp library in your environment? As server?

princetomy92 commented 6 years ago

hii sir ,receive no data regardless of amount of time I let the application open. my application is working with socket connection ,but some times not get any messages. socket opened.but not get any messages. please help me.thanks in advance.

my codes

using (var ws = new WebSocketSharp.WebSocket("ws://26.62.331.251:6666")) {

                        ws.Connect();
                        // MessageBox.Show("test for connect");
                        ws.Send(rqjson_data);

                        MessageBox.Show("rq data sent");

                        //This event occurs when the WebSocket connection has been established....//
                        ws.OnOpen += (sender1, e1) =>
                        {
                           // ws.Send(rqjson_data);
                           // MessageBox.Show(rqjson_data);
                           // ws.Send(" connection  ...");
                           MessageBox.Show("connection success");
                        };

                        //This event occurs when the WebSocket receives a message...//

                        ws.OnMessage += (sender1, e1) =>
                        {

                            Console.Write("Message Recieved");
                            MessageBox.Show("Message Recieved");

                            if (e1.IsText)
                            {
                                MessageBox.Show("text" + e1.Data);
                                Console.Write("Message: " + e1.Data);
                                //message received.

                                dynamic data = JsonConvert.DeserializeObject(e1.Data);
                                MessageBox.Show("data"+data);
                                string from = data.data.from_uri;
                                MessageBox.Show("frrom"+from);

                                return;
                                // ws.Close();
                            }

                            if (e1.IsBinary)
                            {
                                MessageBox.Show("binary " + e1.Data);
                                Console.Write("Binary Data obtained");
                                return;
                            }
                        };
princetomy92 commented 6 years ago

i have done socket program successfully.its working fine.Actually i have done the same code with separate call. I can share my code ,that will help everyone struggling with web socket connection.

please create separate methods for connections and avoid using block otherwise no events will fired.please try update with my code. Thanks websocket-sharp for this package from nuget.

public void socket_connection() { //connecting to server Console.WriteLine("\n 2. started connection with server"); ws = new WebSocketSharp.WebSocket("ws://55.1.111.4:5244");

        ///after connection  send json data contains auth token to server.

        //This event occurs when the WebSocket connection has been established....//
        Uri url = ws.Url;

        Logger log = ws.Log;
        Console.WriteLine("\n"+url.AbsoluteUri);
        Console.WriteLine("\n"+log.Output);
        ws.OnError += Ws_OnError;
        ws.OnClose += Ws_OnClose;
        ws.OnMessage += Ws_OnMessage;
        ws.OnOpen += Ws_OnOpen;

        ws.ConnectAsync();

    }

private void Ws_OnOpen(object sender, EventArgs e) {

        ws.Send(rqjson_data);

        Console.WriteLine("connection success.data send.authenticated");
    }