1. Introduction to WebSocket
For some systems that require high real-time data, such as stock quotes, online chat, and Weibo, data can be realized Real-time push is a must. The usual ways to achieve real-time push are:
1. Polling: Send data every once in a while (such as: webqq)
2. Socket: In the past, ordinary web pages did not support socket Receive message . You can use flash or applet as a socket client
3. Long connection: It means that multiple data packets can be sent continuously on a TCP connection. During the TCP connection maintenance period, if no data packets are sent, both parties need to Send detection packets to maintain this connection. Generally, you need to do
yourself to maintain it online.
----------------------------------------------- --------------------------------------------------
html5Provides a non-http two-way connection through window.WebSocket (window.MozWebSocket under firefox). This connection is real-time and permanent unless displayed colse.
This means that as long as the client opens a Socket and requests a connection (just once), the server can receive and send messages in real time, without manual detection and maintenance state.
The methods and properties provided by WebSocket can be seen by entering Window.WebSocket.prototype in firebug.
The following code lists the basic usage ideas:
var location = "ws://localhost:port/serlet/xxx"; //服务端处理的servlet var webSocket = new WebSocket(location); //webSocket.readyState var readyStates = { "CONNECTING":"正在连接“, ”OPEN“ : "已建立连接", "CLOSING":"正在关闭连接", "CLOSED":"已关闭连接" } webSocket.send(data);//发送数据到服务端,目前只支持文本类型。JSON.stringify(data);JSON.parse(data); webSocket.onMessage = function(event){ var data = event.data;//从服务端过来的数据 } webSocket.onOpen = function(event){ //开始通信 } webSocket.onClose = function(event){ //结束通信 } webSocket.close();
2. An example based on jetty (java server)
Currently, Apache does not support WebSocket. Various languages have their own ways to implement it. It is implemented in Java.
Step 1: Download a jetty, unzip it and put it on any disk. Only jetty7 and above support WebSocket, download address: download.eclipse.org/jetty/stable-7/dist/
Step 2: Download eclipse (MyEclipse is not recommended, it is more troublesome, Need toinstallother plug-ins), must support jetty7, the higher the version, the better.
Step 3: Install the plug-in in eclipse, help---Install new software...----The url is: eclipse-jetty.sourceforge.net/update/
Step 4: Create a new Dynamic Web Project
The directory structure is as follows
.
TailorWebSocketServlet.javapackage com.test; import java.io.IOException; import java.util.Date; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.websocket.WebSocket; import org.eclipse.jetty.websocket.WebSocketServlet; public class TailorWebSocketServlet extends WebSocketServlet { private static final long serialVersionUID = -7289719281366784056L; public static String newLine = System.getProperty("line.separator"); private final Set<TailorSocket> _members = new CopyOnWriteArraySet<TailorSocket>(); private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); public void init() throws ServletException { super.init(); executor.scheduleAtFixedRate(new Runnable() { public void run() { System.out.println("Running Server Message Sending"); for(TailorSocket member : _members){ System.out.println("Trying to send to Member!"); if(member.isOpen()){ System.out.println("Sending!"); try { member.sendMessage("from server : happy and happiness! "+new Date()+newLine); } catch (IOException e) { e.printStackTrace(); } } } } }, 2, 2, TimeUnit.SECONDS); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { getServletContext().getNamedDispatcher("default").forward(request, response); } public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { return new TailorSocket(); } class TailorSocket implements WebSocket.OnTextMessage { private Connection _connection; public void onClose(int closeCode, String message) { _members.remove(this); } public void sendMessage(String data) throws IOException { _connection.sendMessage(data); } public void onMessage(String data) { System.out.println("Received: "+data); } public boolean isOpen() { return _connection.isOpen(); } public void onOpen(Connection connection) { _members.add(this); _connection = connection; try { connection.sendMessage("onOpen:Server received Web Socket upgrade and added it to Receiver List."); } catch (IOException e) { e.printStackTrace(); } } } }
<!DOCTYPE HTML> <html> <head> <meta charset = "utf-8"/> <title>Chat by Web Sockets</title> <script type='text/javascript'> if (!window.WebSocket) alert("window.WebSocket unsuport!"); function $() { return document.getElementById(arguments[0]); } function $F() { return document.getElementById(arguments[0]).value; } function getKeyCode(ev) { if (window.event) return window.event.keyCode; return ev.keyCode; } var server = { connect : function() { var location ="ws://localhost:8888/servlet/a"; this._ws =new WebSocket(location); this._ws.onopen =this._onopen; this._ws.onmessage =this._onmessage; this._ws.onclose =this._onclose; }, _onopen : function() { server._send('send to server : websockets are open for communications!'); }, _send : function(message) { if (this._ws) this._ws.send(message); }, send : function(text) { if (text !=null&& text.length >0) server._send(text); }, _onmessage : function(m) { if (m.data) { var messageBox = $('messageBox'); var spanText = document.createElement('span'); spanText.className ='text'; spanText.innerHTML = m.data; var lineBreak = document.createElement('br'); messageBox.appendChild(spanText); messageBox.appendChild(lineBreak); messageBox.scrollTop = messageBox.scrollHeight - messageBox.clientHeight; } }, _onclose : function(m) { this._ws =null; } }; </script> <style type='text/css'> div { border: 0px solid black; } div#messageBox { clear: both; width: 40em; height: 20ex; overflow: auto; background-color: #f0f0f0; padding: 4px; border: 1px solid black; } div#input { clear: both; width: 40em; padding: 4px; background-color: #e0e0e0; border: 1px solid black; border-top: 0px } div.hidden { display: none; } span.alert { font-style: italic; } </style> </head> <body> <div id='messageBox'></div> <div id='input'> <div> <input id='connect' type='submit' name='Connect' value='Connect' /> </div> </div> <script type='text/javascript'> $('connect').onclick =function(event) { server.connect(); returnfalse; }; </script> <p> JAVA Jetty for WebSocket </p> </body> </html>
xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>tailor</display-name> <servlet> <servlet-name>WebSocket</servlet-name> <servlet-class>com.test.TailorWebSocketServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>WebSocket</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>test.html</welcome-file> </welcome-file-list> </web-app>
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd"> <!-- ================================================================== Configure and deploy the test web application in $(jetty.home)/webapps/test Note. If this file did not exist or used a context path other that /test then the default configuration of jetty.xml would discover the test webapplication with a WebAppDeployer. By specifying a context in this directory, additional configuration may be specified and hot deployments detected. ===================================================================== --> <Configure class="org.eclipse.jetty.webapp.WebAppContext"> <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> <!-- Required minimal context configuration : --> <!-- + contextPath --> <!-- + war OR resourceBase --> <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> <Set name="contextPath">/</Set> <Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set> <Set name="overrideDescriptor"><SystemProperty name="jetty.home" default="."/>/contexts/test.d/override-web.xml</Set> <!-- virtual hosts <Set name="virtualHosts"> <Array type="String"> <Item>www.myVirtualDomain.com</Item> <Item>localhost</Item> <Item>127.0.0.1</Item> </Array> </Set> --> <!-- disable cookies <Get name="sessionHandler"> <Get name="sessionManager"> <Set name="usingCookies" type="boolean">false</Set> </Get> </Get> --> <Get name="securityHandler"> <Set name="loginService"> <New class="org.eclipse.jetty.security.HashLoginService"> <Set name="name">Test Realm</Set> <Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set> <!-- To enable reload of realm when properties change, uncomment the following lines --> <!-- changing refreshInterval (in seconds) as desired --> <!-- <Set name="refreshInterval">5</Set> <Call name="start"></Call> --> </New> </Set> <Set name="checkWelcomeFiles">true</Set> </Get> <!-- Non standard error page mapping --> <!-- <Get name="errorHandler"> <Call name="addErrorPage"> <Arg type="int">500</Arg> <Arg type="int">599</Arg> <Arg type="String">/dump/errorCodeRangeMapping</Arg> </Call> </Get> --> <!-- Add context specific logger <Set name="handler"> <New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler"> <Set name="requestLog"> <New id="RequestLogImpl" class="org.eclipse.jetty.server.NCSARequestLog"> <Set name="filename"><Property name="jetty.logs" default="./logs"/>/test-yyyy_mm_dd.request.log</Set> <Set name="filenameDateFormat">yyyy_MM_dd</Set> <Set name="append">true</Set> <Set name="LogTimeZone">GMT</Set> </New> </Set> </New> </Set> --> </Configure>
The effect after running:
Browser access: localhost:8080On the eclipse console:
Congratulations, you are successful here!
3. PerformanceFor this type of connection, various servers consume different performance. In Java, you can use JDK Check Jconsole in the bin directory. The memory consumption of a single connection is about 2.5M, but the concurrency has not been tested. No pictures here
The above is the detailed content of Code sharing of html5 WebSocket implemented in jetty7. For more information, please follow other related articles on the PHP Chinese website!