Overview
Traditional Web pages are browser to the server "query" data, but in many cases, the most effective way is the server to the browser "send" data. For example, whenever a new e-mail message is received, the server sends a "notification" to the browser, which is more efficient than the browser's time-to-server query (polling).
The server sends the event (Server-sent events, SSE) to solve this problem, and proposes a new API, deployed on the EventSource object. Currently, in addition to IE, other mainstream browsers are supported.
In short, the so-called SSE, is the browser to send an HTTP request to the server, and then the server constantly one-way to the browser push "message" (message). This information is very simple in format, that is, "information" with the prefix "Data:" and then "\ n" ends.
$ curl http://example.com/datesdata: 1394572346452data: 1394572347457data: 1394572348463
SSE and WebSocket have similar functions, which are used to establish communication channels between the browser and the server. The difference between the two is:
The WebSocket is a full-duplex channel that can communicate in two directions and is more powerful; SSE is a one-way channel and can only be sent to the browser by the server.
WebSocket is a new protocol that requires server-side support, and SSE is deployed on top of the HTTP protocol, which is supported by existing server software.
SSE is a lightweight protocol, relatively simple; WebSocket is a heavier protocol, relatively complex.
SSE supports wire break re-connection by default, WebSocket requires additional deployment.
SSE supports custom sent data types.
From the above comparison can be seen, the two have characteristics, suitable for different occasions.
Client Code Overview
First, use the following code to detect if the browser supports SSE.
if (!!window.EventSource) { // ...}
Then, the deployment SSE is probably as follows.
var source = new eventsource< Span class= "P" > ( '/dates ' . OnMessage = function (e) {console. Log (e. Data); }; //or source. Addeventlistener ( "message" function (e) {})
Establish a connection
First, the browser initiates a connection to the server, generating a EventSource instance object.
var source = new EventSource(url);
The parameter URL is the server URL, which must be in the same domain as the URL of the current page, and the protocol and port must be the same.
The following is an instance of establishing a connection.
if (!!window.EventSource) { var source = new EventSource(‘http://127.0.0.1/sses/‘);}
The newly generated EventSource instance object, which has a ReadyState property that indicates the state in which the connection is located.
source.readyState
It can take the following values:
0, equivalent to constant eventsource.connecting, indicating that the connection has not been established, or the connection is disconnected.
1, equivalent to the constant Eventsource.open, indicates that the connection has been established and can accept data.
2, equivalent to constant eventsource.closed, indicates that the connection is broken and is not re-connected.
Open Event
Once the connection is established, the Open event is triggered and the corresponding callback function can be defined.
source.onopen = function(event) { // handle open event};// 或者source.addEventListener("open", function(event) { // handle open event}, false);
Message Event
The message event is triggered when the data is received.
Source.OnMessage=function(Event){VarData=Event.Data;VarOrigin=Event.Origin;VarLasteventid=Event.Lasteventid;Handle message};OrSourceaddeventlistener ( "message" Function (event) {var data = event. Datavar origin = event. Originvar lasteventid = event.lasteventid//handle Message}, false);
The Parameter object event has the following properties:
Data: (text format) of the server-side returns.
Origin: The domain name portion of the server-side URL, which is the protocol, domain name, and port.
Lasteventid: The number of the data sent by the server side. If there is no number, this property is empty.
Error Event
If a communication error occurs (such as a connection interruption), an error event is triggered.
source.onerror = function(event) { // handle error event};// 或者source.addEventListener("error", function(event) { // handle error event}, false);
Custom events
The server can contract custom events with the browser. In this case, the data sent back does not trigger the message event.
Sourceaddeventlistener ( "foo" Function (event) {var data = event. Datavar origin = event. Originvar lasteventid = event.lasteventid//handle Message}, false);
The above code indicates that the browser listens to the Foo event.
Close method
The Close method is used to close the connection.
source.close();
Data Format Overview
The HTTP header information for the data sent by the server is as follows:
Content-Type: text/event-streamCache-Control: no-cacheConnection: keep-alive
Subsequent lines are in the following format:
field: value\n
field can take four values: "Data", "event", "id", or "retry", which means there are four types of header information. Each HTTP communication can contain one or more of these four types of header information. \ n represents a line break.
A line that begins with a colon, indicating a comment. Typically, the server sends a comment to the browser at regular intervals, keeping the connection uninterrupted.
: This is a comment
Here are some examples.
: this is a test stream\n\ndata: some text\n\ndata: another message\ndata: with two lines \n\n
Data: Columns
The data content is represented as a single row or multiple rows. If the data has only one row, end with "\ n" as follows.
data: message\n\n
If the data has more than one row, the last line ends with "\ n" and the preceding row ends with "\ n".
data: begin message\ndata: continue message\n\n
In summary, the last line of data, ending with two newline symbols, indicates the end of the date.
For example, send data in JSON format.
data: {\ndata: "foo": "bar",\ndata: "baz", 555\ndata: }\n\n
ID: Data identifier
The data identifier is represented by an ID, which corresponds to the number of each piece of data.
id: msg1\ndata: message\n\n
The browser reads this value with the Lasteventid property. Once the connection is broken, the browser sends an HTTP header containing a special "Last-event-id" header message that will be sent back to help rebuild the connection on the server side. Therefore, this header information can be considered as a synchronization mechanism.
Event Bar: Custom Information type
The event header information represents the custom data type, or the name of the data.
event: foo\ndata: a foo event\n\ndata: an unnamed event\n\nevent: bar\ndata: a bar event\n\n
The above code creates three messages. The first one is Foo, which triggers the Foo event on the browser side, the second is not named, indicates the default type, triggers the message event on the browser side, and the third bar, which triggers the bar event on the browser side.
Retry: Maximum time interval
The default browser is to start the re-connection if no information is sent in the server side for three seconds. The server side can use the Retry header information to specify the maximum time interval for communication.
retry: 10000\n
Server code
Server-side send events that require the server to remain connected to the browser. For different server software, the resources consumed are not the same. Apache server, each connection is a thread, if you want to maintain a large number of connections, it is bound to consume a lot of resources. node. js is that all connections use the same thread, so the resources consumed are much smaller, but this requires that each connection cannot contain time-consuming operations, such as disk IO read and write.
The following is a code instance of node. JS's server sending events.
varHTTP = require ("http"); Http.createserver (function(req, res) {varFileName = "." +Req.url; if(FileName = = = "./stream") {Res.writehead ($, {"Content-type": "Text/event-stream", "Cache-control": "No-cache", "Connection": "Keep-alive"}); Res.write ("Retry:10000\n"); Res.write ("Event:connecttime\n"); Res.write ("Data:" + (NewDate ()) + "\ n"); Res.write ("Data:" + (NewDate ()) + "\ n"); Interval= SetInterval (function() {Res.write ("Data:" + (NewDate ()) + "\ n"); }, 1000); Req.connection.addListener ("Close",function() {clearinterval (interval); }, false); }}). Listen (80, "127.0.0.1");
PHP code instance.
<?PHPHeader(' Content-type:text/event-stream ');Header(' Cache-control:no-cache ');//We recommend that you do not cache SSE data/** * constructs the SSE data format and flushes that data to the client. * * @param string $id timestamp/id of this con Nection. * @param string $msg Line of text this should be transmitted. */functionSendmsg ($id,$msg) { Echo"ID:$id" .Php_eol; Echo"Data:$msg" .Php_eol; Echo Php_eol; Ob_flush(); Flush();}$serverTime= Time(); Sendmsg ($serverTime, ' Server time: '.Date("H:i:s", Time()));
SSE: Server sends events and uses long links for communication