作者:长东

HTML5给Web浏览器带来了全双工TCP连接websocket标准服务器的能力。

换句话说,浏览器能够与服务器建立连接,通过已建立的通信信道来发送和接收数据而不需要由HTTP协议引入额外其他的开销来实现。

在本教程中我们将在Java EE环境下实现一个简单的websockect服务器端来和客户端进行数据交互。

本教程需要以下环境:

  1. JDK 1.7.0.21
  2. tomcat 7

: Java EE 7中才引入了WebSocket。

WebSocket服务器端

WebSocketServer 代码:
package .websocket;import java.io.IOException;import javax.websocket.OnClose;import javax.websocket.OnError;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.PathParam;import javax.websocket.server.ServerEndpoint; //该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。类似Servlet的注解mapping。无需在web.xml中配置。@ServerEndpoint("/webSocketServer/{userId}")public class WebSocketServer {         /**     * 连接建立成功调用的方法     * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据     * @throws IOException      */    @OnOpen    public void onOpen(@PathParam("userId") String userId,Session session) throws IOException{       /* if(userId!=null){                        if(!SocketUtils.hasConnection(userId)){                SocketUtils.put(userId,session);            }            else{                //相同用户只允许在一个地方登录(网页版内部判断)。                SocketUtils.sendMessage(userId,"forcelogout","该用户已在其他地方登录,此次登录将被强制退出。",0,"");                  SocketUtils.remove(userId,session.getId());                SocketUtils.put(userId,session);            }        }*/        System.out.println("Client connected  "+userId);    }         /**     * 连接关闭调用的方法     */    @OnClose    public void onClose(@PathParam("userId") String userId,Session session)throws IOException{        //SocketUtils.remove(userId,session.getId());        System.out.println("Connection closed");    }         /**     * 收到客户端消息后调用的方法     * @param message 客户端发送过来的消息     * @param session 可选的参数     * @throws IOException      */    @OnMessage    public void onMessage(@PathParam("userId") String userId,String message, Session session) throws IOException {        // Print the client message for testing purposes        System.out.println("Received: " + message);               // Send the first message to the client        session.getBasicRemote().sendText("This is the first server message");               // Send 3 messages to the client every 5 seconds        int sentMessages = 0;        while(sentMessages < 3){          session.getBasicRemote().            sendText("This is an intermediate server message. Count: "              + sentMessages);          sentMessages++;        }               // Send a final message to the client        session.getBasicRemote().sendText("This is the last server message");    }         /**     * 发生错误时调用     * @param session     * @param error     */    @OnError    public void onError(Session session, Throwable error){        error.printStackTrace();    }}

你可能已经注意到我们从 javax.websocket包中引入了一些类。

@ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端。注解的值将被用于监听用户连接的终端访问URL地址。

onOpen 和 onClose 方法分别被@OnOpen@OnClose 所注解。这两个注解的作用不言自明:他们定义了当一个新用户连接和断开的时候所调用的方法。

onMessage 方法被@OnMessage所注解。这个注解定义了当服务器接收到客户端发送的消息时所调用的方法。注意:这个方法可能包含一个javax.websocket.Session可选参数(在我们的例子里就是session参数)。如果有这个参数,容器将会把当前发送消息客户端的连接Session注入进去。

本例中我们仅仅是将客户端消息内容打印出来,然后首先我们将发送一条开始消息,之后间隔5秒向客户端发送1条测试消息,共发送3次,最后向客户端发送最后一条结束消息。

WebSocket客户端

index.jsp代码:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><html><head><title>Testing websocketstitle>head><body>    <div>        <input type="submit" value="Start" onclick="start()" />    div>    <div id="messages">div>    <script type="text/javascript">    //建立websocket连接     var websocket = new WebSocket('ws://localhost:8080/bing/webSocketServer/bing');              websocket.onopen = function (evnt) {           document.getElementById('messages').innerHTML           = 'Connection established';       };       websocket.onmessage = function (evnt) {           document.getElementById('messages').innerHTML           += '
' + event.data;       };       websocket.onerror = function (evnt) {       };       websocket.onclose = function (evnt) {       };     function start() {      websocket.send('hello');      return false;    }script>body>html>

这是一个简单的页面,包含有JavaScript代码,这些代码创建了一个websocket连接到websocket服务器端。

onOpen 我们创建一个连接到服务器的连接时将会调用此方法。

onError 当客户端-服务器通信发生错误时将会调用此方法。

onMessage 当从服务器接收到一个消息时将会调用此方法。在我们的例子中,我们只是将从服务器获得的消息添加到DOM。

我们连接到websocket 服务器端,使用构造函数 new WebSocket() 而且传之以端点URL:

ws://localhost:8080/bing/webSocketServer/bing  ---bing 后台的userid

测试

现在我们可以访问测试页面对我们的应用进行测试:

http://localhost:8080/bing/index.jsp

Java socket服务器端无响应_Java socket服务器端无响应

Java socket服务器端无响应_java websocket服务器_02

后台:

Java socket服务器端无响应_Java socket服务器端无响应_03