As the title suggests, should Ping Frames only be sent from a server or it is better to have both endpoints send them? As mentioned in the Websocket RFC:
NOTE: A Ping frame may serve either as a keepalive...
So by by having one endpoint sending a ping request it should keep the connection open, right?
The second part of above line is this:
or as a means to verify that the remote endpoint is still responsive.
I'm new to the concept of websockets but if the connection closes from the server won't the client be notified?
Consider the case where the server just goes away, maybe it crashes. Who or what will notify the client of this? Or say a network link close to the server is down for so long that by the time it comes back up, the server has totally forgotten about this client. Who or what would tell the client?
There are three possibilities:
The client does not need to detect loss of the connection. In this case, there's nothing special you need to do.
The client has some way to detect loss of the connection already. For example, if the connection is idle for some period of time, the client could send an application-level query and timeout if it gets no response or if the query fails.
The client needs to detect loss of the connection but has no existing way to do this. In this case, using pings makes sense.
In a typical query/response protocol, the client usually doesn't need to ping the server because there's some query it can send that has the same effect. Unless the protocol layered above websocket supports some way for the server to query the client, the server often has only two choices: use pings to detect lost connections or disconnect idle clients.
Both variants has ways of implementation. For example in case if server sends ping to client, then client can get information that server disconnected by have a loop with deadline timer which is reset every time when ping is received. If the timer reaches dealine, then it's mean that server disconnected.
Related
I understand that http2 uses one tcp connection to serve multiple requests, for example, if I request index.html which contains a.css and a.js, these three requests will be done in one tcp connection.
What happens if user clicks index2.html? does this request still use the same previous tcp connection? If so, will the browser keep the connection open until user closes the browser? And on the server side, does the server keep many connections open all the time?
When using HTTP/2, browsers typically open only one connection per domain.
In your example, index2.html will be sent on the same TCP connection that was used for index.html, a.css and a.js.
In HTTP/2 requests are multiplexed on the same TCP connection, so that the browser can send them concurrently, without waiting for a previous request to be responded to.
Both browsers and servers have an idle timeout for TCP connections.
If the connection is idle for long enough, it will be closed by either party - the one that has the shorter idle timeout, to save resources.
For example, you may open a connection to a wikipedia.org, perform a few requests, and then leave that tab and work on something else.
After a while (typically 30 seconds) the browser will close the TCP connection to wikipedia.org.
On the server side, the server will keep the connections from various clients open, until they are either closed by the client or until the server-side idle timeout fires, at which point it's the server that initiated the close of the TCP connection.
With HTTP/2, the number of connections that a server has to maintain is vastly less than it was with HTTP/1.1.
With HTTP/2, a server has to maintain just 1 TCP connection per client; with HTTP/1.1, the server had to maintain typically 2-8 TCP connections per client.
What happens if user clicks index2.html? does this request still use the same previous tcp connection?
Yes. On top of that, multiple browser tabs/windows also share a single HTTP/2 connection.
If so, will the browser keep the connection open until user closes the browser?
Below from RFC - connection management
For best performance, it is expected that clients will not close
connections until it is determined that no further communication with
a server is necessary (for example, when a user navigates away from a
particular web page) or until the server closes the connection.
Clients SHOULD NOT open more than one HTTP/2 connection to a given
host and port pair.
And on the server side, does the server keep many connections open all the time?
Servers are encouraged to maintain open connections for as long as
possible but are permitted to terminate idle connections if necessary.
When either endpoint chooses to close the transport-layer TCP
connection, the terminating endpoint SHOULD first send a GOAWAY
(Section 6.8) frame so that both endpoints can reliably determine
whether previously sent frames have been processed and gracefully
complete or terminate any necessary remaining tasks.
More info on connection error below.
RFC connection-error-handling
A connection error is any error that prevents further processing of
the frame layer or corrupts any connection state. An endpoint that
encounters a connection error SHOULD first send a GOAWAY frame with
the stream identifier of the last stream that it successfully received
from its peer. The GOAWAY frame includes an error code that indicates
why the connection is terminating. After sending the GOAWAY frame for
an error condition, the endpoint MUST close the TCP connection. It is
possible that the GOAWAY will not be reliably received by the
receiving endpoint. In the event of a connection error, GOAWAY only
provides a best-effort attempt to communicate with the peer about why
the connection is being terminated.
An endpoint can end a connection at any time. In particular, an
endpoint MAY choose to treat a stream error as a connection error.
Endpoints SHOULD send a GOAWAY frame when ending a connection,
providing that circumstances permit it.
I've read some articles comparing the differences between WebSocket and the other push methods like Long polling. All the conclusions tend to be WebSocket is better then HTTP with low latency in the server and client bidirectional communication process.
But if server push is not a must, for example, a client game program just make a few queries to the server for some information, does it still better to use WebSocket then HTTP? More specially, I have two doubts here:
1. In a single Request-Response procedure, which is more efficency ? (I establish a WebSocket connection each time querying in the above case.)
2. Will the server capacity (The total number of clients that the server can serve) be affected by the unnecessary long-lived connection if I keep an WebSocket connection during the life cycle of the client?
Added Question:
3. Suppose there is only one TCP connection between the server and the client, will the stability of the connection go down and down as time flows?
The basic thing behind both the WebSocket and HTTP is the socket. In HTTP, it opens a connection on request and closes on response. For WebSocket, concept is a 2 way communication (full duplex) rather than request-response cycle.
Answers to your question:
Either you can use HTTP server or can create request-response design
using WebSocket
That's obvious. Each connection is a socket object. Server capacity
will be affected if we are not managing connections.
In WebSocket, it's using ping-pong mechanism to make sure that the client or
the server is alive. For every ping requests from one end, other end is
subjected to reply a pong response. This mechanism helps to detect failures and hence to maintain stability.
I just went through the specification of http 1.1 at http://www.w3.org/Protocols/rfc2616/rfc2616.html and came across a section about connections http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8 that says
" A significant difference between HTTP/1.1 and earlier versions of HTTP is that persistent connections are the default behavior of any HTTP connection. That is, unless otherwise indicated, the client SHOULD assume that the server will maintain a persistent connection, even after error responses from the server.
Persistent connections provide a mechanism by which a client and a server can signal the close of a TCP connection. This signaling takes place using the Connection header field (section 14.10). Once a close has been signaled, the client MUST NOT send any more requests on that connection. "
Then I also went through a section on http state management at https://www.rfc-editor.org/rfc/rfc2965 that says in its section 2 that
"Currently, HTTP servers respond to each client request without relating that request to previous or subsequent requests;"
A section about the need to have persistent connections in the RFC 2616 also said that prior to persistent connections every time a client wished to fetch a url it had to establish a new TCP connection for each and every new request.
Now my question is, if we have persistent connections in http/1.1 then as mentioned above a client does not need to make a new connection for every new request. It can send multiple requests over the same connection. So if the server knows that every subsequent request is coming over the same connection, would it not be obvious that the request is from the same client? And hence would this just not suffice to maintain the state and would this just nit be enough for the server to understand that the request was from the same client ? In this case then why is a separate state management mechanism required at all ?
Basically, yes, it would make sense, but HTTP persistent connections are used to eliminate administrative TCP/IP overhead of connection handling (e.g. connect/disconnect/reconnect, etc.). It is not meant to say anything about the state of the data moving across the connection, which is what you're talking about.
No. For instance, there might an intermediate (such as a proxy or a reverse proxy) in the request path that aggregates requests from multiple TCP connections.
See http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p1-messaging-21.html#intermediaries.
Let's say I am going to deploy a server application that's likely to be placed behind a NAT/firewall and I don't want to ask users to tweak their NAT port mapping. In other words, connections to the server are impossible, but my app is a server application by nature, i.e. it sends back objects per URI.
Now, I'm thinking about initiating connections from the server periodically to see what requests are there to be responded to. I'm going to use HTTP via port 80 as something that would likely be working through NAT/firewall from virtually anywhere.
The question is, are there any standard considerations and common practices of implementing a client that can act as a server at the application level, specifically using HTTP? Any special HTTP headers? Design patterns?
E.g. I am thinking about the following scheme:
The client (which is my logical server) sends a dummy HTTP request to the server
The server responds back with non-standard headers X-Request-URI:, X-Host:, X-If-Modified-Since: etc, in other words, request headers wrapped into X-xxx as they are not standard in this situation; also requests to keep the connection alive
The client responds with a POST request that sends the requested object; again, uses wrapped headers (e.g. X-Status:, etc)
Unless there is a more "standard" way of doing something like this, do you think my approach is plausible?
Edit: an interesting discussion took place on reddit here
I've done something similar. This is very common. Client initiate the connection to the Server and keep the connection ALIVE. If the session is shut-down, client would re-initiate. When the session is up, Server can push anything to the client since it's client initiated.
I am working on linux.
I have a HTTP client which requests some data from the HTTP server. The HTTP client is written in C and HTTP server is written in perl.
I want to simulate TCP re-transmission timeouts at the client end.
I assume that closing the socket gracefully would not result in client to re-transmit the requests.
So I tried the following scenario:
Exit the Server as soon as it gets the HTTP GET request. However, I noticed that once the application exits, the socket is still closed gracefully. I see that the server initiates FIN.ACK messages towards the client even though the application has not called "close" on the socket. I have noticed this behaviour on a simple TCP server and client written in C program as well.
Server does not send any response to the client's GET request. In this case I notice that there is still FIN, ACK sent by the server.
Seems that in these cases the OS (linux) takes care of closing the socket with the peer.
Is there any way to suppress this behaviour (using ioctl or setsockopt options) or any other way to simulate the TCP re-transmission timeouts.
You could try setting firewall rules that block the packets going from the server to the client, which would cause the client to re-transmit the quests. On Linux, this would probably be done using iptables, but different distributions have different methods of controlling it.
This issue was previously discussed here