-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Websocket closes after being open #441
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
You MUST ping websockets. It's part of the protocol. That's how the server knows the client is still there. |
@Gillardo What is your javascript implementation for webscoket |
I'll just add that if you ping the socket from the server side clients will automatically pong. It has proven to be enough for me. |
My websocket javscript implementation is very simple, its used for angular2 and looks like this.
|
All i need is for the client to open a connection and listen for a message. Once a message is received, the client will do something. This works if i use |
Have you checked for exceptions on the server side? |
I have to bring this question up again: As far as I see none of the NodeJS oder Browser implementations of WebSocket clients seem to send out a ping - which causes |
On my implementation I spawn a thread that every n seconds loops the list of active sockets and pings them all. |
@LordFokas be very interested in that code 😄 |
BE ADVISED THIS MIGHT BE SUB-OPTIMAL, THIS WAS SOMEWHAT OF A HACK THAT WORKED AND I KEPT package mohawk.http.servers;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import mohawk.api.http.IWebSocketHandler;
import mohawk.http.HandlerRegistry;
import mohawk.http.MohawkWebSocket;
import fi.iki.elonen.NanoWSD;
public class MohawkWSD extends NanoWSD{
private static final byte[] PING_PAYLOAD = "1337DEADBEEFC001".getBytes();
private List<MohawkWebSocket> toAdd, toRemove;
private Thread wsPinger;
public MohawkWSD(String hostname, int port) {
super(hostname, port);
}
@Override
public void start() throws IOException {
super.start();
toRemove = new LinkedList<>();
toAdd = new LinkedList<>();
wsPinger = new Thread(new Runnable(){
@Override public void run(){
List<MohawkWebSocket> active = new LinkedList<>();
long nextTime = System.currentTimeMillis();
while(MohawkWSD.this.isAlive()){
nextTime += 4000L;
while(System.currentTimeMillis() < nextTime){
try{ Thread.sleep(nextTime - System.currentTimeMillis()); }
catch(InterruptedException ignored){}
}
synchronized(toAdd){
active.addAll(toAdd);
toAdd.clear();
}
synchronized(toRemove){
active.removeAll(toRemove);
toRemove.clear();
for(MohawkWebSocket ws : active){
try{ ws.ping(PING_PAYLOAD); }
catch(Exception e){ toRemove.add(ws); }
}
}
}
}
});
wsPinger.setDaemon(true);
wsPinger.start();
}
@Override
public final MohawkWebSocket openWebSocket(IHTTPSession handshake) {
IWebSocketHandler handler = HandlerRegistry.WS_REGISTRY.getHandler(handshake.getUri());
MohawkWebSocket socket = new MohawkWebSocket(this, handshake, handler);
synchronized(toAdd){
if(!toAdd.contains(socket))
toAdd.add(socket);
}
return socket;
}
public final void onSocketClose(MohawkWebSocket socket){
synchronized(toRemove){
if(!toRemove.contains(socket))
toRemove.add(socket);
}
}
} I also override the sockets like this, to keep track of missed pings: @Override
public void ping(byte[] payload) throws IOException {
super.ping(payload);
this.ping++;
if(ping - pong > 3) close(CloseCode.GoingAway, "Missed too many ping requests.", false);
}
@Override
protected void onPong(WebSocketFrame pong){
this.pong++;
} |
You see, my goal with the changes I attempted to introduce to NanoHTTPD in 3.0 were exactly aiming to allow setting up the system like a pipeline, where you can change components independently to add or modify behavior seamlessly in each stage. It still has a long way to go, and I'm not sure which version of the code I'm using here, it might be a commit somewhere between versions, but this should work regardless. |
@LordFokas Thanks for providing your code - now I think I understand the behaviour a little bit better. |
Feel free to give me feedback on it ;) |
It's probably better to use a SecheduledExecutorService( |
@NoahAndrews that's for when you want to write proper code that performs. I just hacked at it until it worked and stopped there, had way more pressing matters to attend to :p |
Yeah, I get it. You did say this though:
|
Ah yes, I meant something more like if it didn't work as expected so I could have a look at my own mess |
Gotcha gotcha. I'll probably post a link to my implementation once it's finished and publicly viewable, for anyone else who stumbles upon this issue. |
I am also having the same difficulties. Is there a cleaner way to deal with the need to ping the sockets, than the one @LordFokas posted? It seems like a lot of trouble just to pacify NanoWSD into not closing the connection. I think perhaps this should be bumped from a question to a bug? |
I simplified the code a bit by using public class MyWebSocket extends WebSocket {
private TimerTask ping = null;
....
@Override
protected void onOpen() {
if (ping == null) {
ping = new TimerTask() {
@Override
public void run(){
try { ping(PING_PAYLOAD); }
catch (IOException e) { ping.cancel(); }
}
};
new Timer().schedule(ping, 1000, 2000);
}
}
@Override
protected void onClose(NanoWSD.WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) {
if (ping != null) ping.cancel();
}
....
} |
(Sorry - i posted this on another thread.. which is CLOSED.. soo.. may help here too ) Same thing here.. Simple FIX. If you follow the class trail you end up at Line 165 of NanoHTTPD.. public static final int SOCKET_READ_TIMEOUT = 5000; ..Just change that. OR.. better.. If you dig a little deeper you'll notice public void start(final int timeout) throws IOException { And just the plain start() is called in the echosocket.. just switch it for the one where you specify a timeout. Set to 0 for no timeout. It works. Big Up LordFokas for sharing this great little project with all of us.. :) |
I hope this PR is helpful for someone in trouble with WebSocket. |
Exception(Read timed out) and "close the connection". The reason is: Do like this: const val HEARTBEAT_INTERVAL: Long = 2 * 60 * 1000
//bigger than heartbeat interval
const val WEBSOCKET_READ_TIMEOUT = HEARTBEAT_INTERVAL + 30
//Start your server like this:
websocketServer.start(WEBSOCKET_READ_TIMEOUT, false)
//in your XXWebSocket onOpen(), ping periodically:
override fun onOpen() {
httpServer.connections.add(this)
httpServer.heartbeatScope.launch { //you can change into singleThreadExecutor or other.
while (isActive) {
try {
ping(PING_PAYLOAD)
} catch (e: IOException) {
onException(e)
}
delay(HEARTBEAT_INTERVAL)
}
}
} |
Anyone have a problem with websockets? I have created my class but once i connect to the websocket, it close after about 2-3 seconds, with a code of 1006.
Here is my code, if anyone knows of anything i have done wrong.
And i have also created a webSocket class
I am guessing this is all ok?? Why would the websocket be disconnecting after a couple seconds?
The text was updated successfully, but these errors were encountered: