Java EE HTML5 WebSocket 示例 已翻译 100%

oschina 投递于 2013/08/14 08:30 (共 5 段, 翻译完成于 08-14)
阅读 119236
收藏 182
27
加载中

在本教程中,我们将借助于Java EE的WebSocket(服务器端)实现一个HTML5的WebSocket连接。

1. 介绍

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

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

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

本教程需要以下环境:

  1. Ubuntu 12.04
  2. JDK 1.7.0.21
  3. Glassfish 4.0
: Java EE 7中才引入了WebSocket。
 
bigtiger02
翻译于 2013/08/14 11:12
4

2. WebSocket服务器端

让我们定义一个 Java EE websocket服务器端:

WebSocketTest.java

package com.byteslounge.websockets;

import java.io.IOException;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/websocket")
public class WebSocketTest {

  @OnMessage
  public void onMessage(String message, Session session) 
    throws IOException, InterruptedException {
  
    // 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){
      Thread.sleep(5000);
      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");
  }
  
  @OnOpen
  public void onOpen() {
    System.out.println("Client connected");
  }

  @OnClose
  public void onClose() {
    System.out.println("Connection closed");
  }
}
你可能已经注意到我们从 javax.websocket包中引入了一些类。

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

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

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

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

bigtiger02
翻译于 2013/08/14 13:38
2

3. 客户端

现在我们要来写websocket测试应用的客户端:

page.html

<!DOCTYPE html>
<html>
<head>
<title>Testing websockets</title>
</head>
<body>
  <div>
    <input type="submit" value="Start" onclick="start()" />
  </div>
  <div id="messages"></div>
  <script type="text/javascript">
    var webSocket = 
      new WebSocket('ws://localhost:8080/byteslounge/websocket');

    webSocket.onerror = function(event) {
      onError(event)
    };

    webSocket.onopen = function(event) {
      onOpen(event)
    };

    webSocket.onmessage = function(event) {
      onMessage(event)
    };

    function onMessage(event) {
      document.getElementById('messages').innerHTML 
        += '<br />' + event.data;
    }

    function onOpen(event) {
      document.getElementById('messages').innerHTML 
        = 'Connection established';
    }

    function onError(event) {
      alert(event.data);
    }

    function start() {
      webSocket.send('hello');
      return false;
    }
  </script>
</body>
</html>

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

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

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

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

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

ws://localhost:8080/byteslounge/websocket

super0555
翻译于 2013/08/14 09:33
2

4. 测试

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

http://localhost:8080/byteslounge/page.html

正如所期望的,我们将看到 Connection established 消息:

http://localhost:8080/byteslounge/page.html

现在只要我们一按按钮,就会通过此websocket发送初始化报文给服务器,而且接下来会收到发自服务器的测试消息:

服务器发送、客户端接收的消息

super0555
翻译于 2013/08/14 09:38
2

5. WebSockets 握手

客户端和服务器端TCP连接建立在HTTP协议握手发生之后。通过HTTP流量调试,很容易观察到握手。客户端一创建一个 WebSocket实例,就会出现如下请求和服务器端响应:

注意: 我们只录入了WebSocket握手所用到的HTTP头。

请求:

GET /byteslounge/websocket HTTP/1.1
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: wVlUJ/tu9g6EBZEh51iDvQ==

响应:

HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: websocket
Sec-WebSocket-Accept: 2TNh+0h5gTX019lci6mnvS66PSY=

注意:进行连接需要将通过Upgrade and Upgrade将协议升级到支持websocket HTTP头的Websocket协议。服务器响应表明请求被接受,协议将转换到WebSocket协议(HTTP状态码101):

HTTP/1.1 101 Web Socket Protocol Handshake

6. 下载源码

在本页的末尾有范例源代码下载链接,源码在Glassfish 4(需要兼容Java EE 7的服务器)上通过测试。
在如下地址下载范例源码:
bigtiger02
翻译于 2013/08/14 13:58
3
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(64)

老农民28
web实时推送技术使用越来越广泛,但是自己开发又太麻烦了,我觉得没有那个必要,GoEasy就挺不错的,服务器稳定,代码简洁易懂;官网: http://goeasy.io/
明月不懂
明月不懂

引用来自“liubsh”的评论

tomcat 7 java 7
WebSocket connection to 'ws://localhost:8080/websocket' failed: Unexpected response code: 404

引用来自“ptrr”的评论

同样错误!
我的没有这样的错误,不要配置tomcat的websocket包
ptrr
ptrr

引用来自“明月不懂”的评论

<!-- Spring websocket -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-websocket</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-messaging</artifactId>
      <version>${spring.version}</version>
    </dependency>


<!-- JSR 356: Java API for WebSocket -->
    <dependency>
   <groupId>javax.websocket</groupId>
   <artifactId>javax.websocket-api</artifactId>
   <version>${websocket.version}</version>
   <scope>provided</scope>
</dependency>
<!--
    <dependency>
      <groupId>org.apache.tomcat</groupId>
      <artifactId>tomcat-websocket-api</artifactId>
      <version>${tomcat.version}</version>
      <scope>provided</scope>
    </dependency>
    -->


jdk,1.7.0_45,tomcat7.0.64 不好使,还是那个错误
ptrr
ptrr

引用来自“liubsh”的评论

tomcat 7 java 7
WebSocket connection to 'ws://localhost:8080/websocket' failed: Unexpected response code: 404
同样错误!
ptrr
ptrr
WebSocket connection to 'ws://localhost:8080/websocket' failed: Error during WebSocket handshake: Unexpected response code: 404




page.html:42 WebSocket is already in CLOSING or CLOSED state.

这两个怎么破?
ydww
ydww
实测结果,好像只能支持200个链接,后边的都连接不上了
f
fieldcatalog
alert(undefined)的朋友,试一下如下解决办法:
把html文件中的url改为:
new WebSocket('ws://localhost:8080/com-byteslounge-websockets/websocket');
德德豸

引用来自“明月不懂”的评论

最后这些问题都解决了,大家注意 因为tomcat自带了websocket-api.jar,所以项目的pom文件中应该为
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-websocket-api</artifactId>
<version>7.0.55</version>
<scope>provided</scope>
</dependency>
正解!十分感谢
黄耀煌
黄耀煌
http://www.blue-zero.com/WebSocket/ 在线WebSocket测试工具,采用c#,需要完整客户端/服务器源码请在该URL里的【发送的内容】写上联系方式
gggggame
gggggame

引用来自“yonge”的评论

引用来自“yonge”的评论

我的打开页面就弹出错误窗口:undefined。
JavaEE7 / JDK7U51 / wildfly 8 / chrome28
Unexpected response code: 404

改用FF浏览器,提示:
Firefox 无法建立到 ws://localhost:8080/wechat/websocket 服务器的连接。
new WebSocket('ws://localhost:8080/wechat/websocket');

已解决:是因为我的项目使用了Struts2,在Web.xml中定义了过滤器:StrutsPrepareAndExecuteFilter。这个过滤器会对websockets的请求进行过滤。
现在的解决方案是:自定义一个过滤器,放过所有的websocket请求。
具体怎么做的?
返回顶部
顶部
返回顶部
顶部