Websocket connection closes after about 10s

4,539 views
Skip to first unread message

Morgan McGuire

unread,
Mar 25, 2013, 11:33:31 AM3/25/13
to mongoos...@googlegroups.com
I'm successfully creating a websocket connection from Chrome to Mongoose, and sending data both ways.  After about 10s of inactivity, Mongoose reports that the client has terminated the connection (the client then fires its WebSocket.onclose method in JavaScript).

Is this normal?  Do I have to send manual keep-alive packets or something?

-m

Morgan McGuire

unread,
Mar 25, 2013, 12:51:53 PM3/25/13
to mongoos...@googlegroups.com
It looks like the server has to send a "ping" packet (bits = 0x9) periodically or the client will close connection.  Mongoose doesn't send these automatically, so connections drop.

It is a little awkward to send them from outside of Mongoose because there is no exposed list of the connections, and it wouldn't be threadsafe to invoke mg_printf (which calls write(), which calls push(), which calls send()) from the main application thread even if those connections were exposed.  However, there is already the thread synchronization problem of the server needing to send data to the client at arbitrary times, which I don't understand how to synchronize under the API.

-m

David Lethe

unread,
Mar 25, 2013, 1:01:47 PM3/25/13
to mongoos...@googlegroups.com
It is not the job of the webserver to keep connections open forever.  If it did then the internet would quickly become unusable because people wouldn't be able to close windows or move onto other websites w/o informing web servers that they are done with a site.   The amount of time a client browser keeps a connection open after a request for information has been processed is highly O/S, browser, driver specific.   If you want to keep the connection open, then you'll have to add javascript code to make a request for something every X seconds.


--
You received this message because you are subscribed to the Google Groups "mongoose-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mongoose-user...@googlegroups.com.
To post to this group, send email to mongoos...@googlegroups.com.
Visit this group at http://groups.google.com/group/mongoose-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Morgan McGuire

unread,
Mar 25, 2013, 1:23:51 PM3/25/13
to mongoos...@googlegroups.com
Websockets specifically have ping and pong frames that are used for keeping connections alive: http://tools.ietf.org/html/rfc6455#section-5.5.2

This is so that the application protocol doesn't have to be cluttered with similar messages.  It makes sense for the server to send the ping--it is the one should be (more) concerned about its resource pool being consumed and wants to close connections if the other side is not responding.

-m

Morgan McGuire

unread,
Mar 25, 2013, 4:02:44 PM3/25/13
to mongoos...@googlegroups.com
(there is no way of sending these from JavaScript, and clients don't initiate them--it really appears to be the server's responsibility).

Below is a general-purpose function for sending a message to a websocket client.  I'm now working on enumerating the connections and looking for a simple way of guaranteeing that they are locked correctly so that send calls don't get interlaced.

/**
 Send a message to a client.

 This should not be invoked on a connection while any other mg_write/mg_printf operation
 is occuring on that connection.  Mongoose does not provide a per-connection mutex,
 so it is necessary for the application to either hold a global lock on mg_write, or
 to hold a table mapping connections to locks.

 Note that POSIX/Winsock's send() is threadsafe
 but mongoose's mg_printf/mg_write is not (because of the loop in push(), although that is only
 a problem if the packet is large or outgoing buffer is full).
 */
void websocket_write(struct mg_connection* conn, int opcode, const char* data, size_t dataLen) {
    unsigned char* copy = (unsigned char*)malloc(dataLen + 4);
    size_t copyLen = 0;
    copy[0] = 0x80 + (opcode & 0xF);

    if (dataLen < 126) {
        copy[1] = dataLen;
        System::memcpy(copy + 2, data, dataLen);
        copyLen = 2 + dataLen;
    } else if (dataLen < 0xFFFF) {
        copy[1] = 126;
        *(uint16*)(data + 2) = htons(dataLen);
        System::memcpy(copy + 4, data, dataLen);
        copyLen = 4 + dataLen;
    } else {
        alwaysAssertM(false, "Packets of length larger than 16 bits are not supported in this implementation.");
    }
    mg_write(conn, copy, copyLen);
    free(copy);
}

-m

Ulrich Hertlein

unread,
Mar 25, 2013, 9:30:59 PM3/25/13
to mongoos...@googlegroups.com
Hi Morgan,

> if (dataLen < 126) {
>...
> } else if (dataLen < 0xFFFF) {
> copy[1] = 126;
> *(uint16*)(data + 2) = htons(dataLen);

This might be a copy-and-paste error, but I guess that should be

*(uint16*)(copy + 2) = htons(dataLen);

/ulrich

Morgan McGuire

unread,
Mar 25, 2013, 9:40:00 PM3/25/13
to mongoos...@googlegroups.com
Thanks! I fixed that and a few other things.

I also extended this into a full patch to allow asynchronous access
under websockets by embedding a mutex when a websocket connection is
created and providing a connection close handler. I'm submitting a
pull request now. This is my first time ever using Git, so I'm not
sure how well this will go...

-m

Prof. Morgan McGuire
Computer Science Department
Williams College
http://cs.williams.edu/~morgan
> --
> You received this message because you are subscribed to a topic in the Google Groups "mongoose-users" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/mongoose-users/EWQ_UgB6hsI/unsubscribe?hl=en.
> To unsubscribe from this group and all its topics, send an email to mongoose-user...@googlegroups.com.

Morgan McGuire

unread,
Mar 25, 2013, 10:34:16 PM3/25/13
to mongoos...@googlegroups.com
My patched version is here, including a new connection_close handler, synchronized access to mg_write, and the mg_websocket_write helper function.  This provides the minimum needed features for server-side application support of websockets.


The recently added Git attributes are not working for me, so this is unfortunately showing every line as having changed even though only about 50 lines changed. 

-m
> To unsubscribe from this group and all its topics, send an email to mongoose-users+unsubscribe@googlegroups.com.
> To post to this group, send email to mongoose-users@googlegroups.com.

Azman M. Yusof

unread,
Mar 30, 2013, 6:20:55 PM3/30/13
to mongoos...@googlegroups.com
It's the line-end thingy... your text editor have converted the whole file to LF from the original CRLF.
> To unsubscribe from this group and all its topics, send an email to mongoose-user...@googlegroups.com.
> To post to this group, send email to mongoos...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages