Java EE HTML5 WebSocket 示例 已翻译 100%

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

In this tutorial we will implement an HTML5 websocket resorting to the Java EE websocket implementation (ServerEndpoint).

1. Introduction

The HTML5 specification brought the capability for web browsers to establish full-duplex TCP connections with websocket compliant servers.

In other words, browsers are now able to establish a connection with a server and keep sending or receiving data through that same established communication channel without the need of the overhead introduced by the HTTP protocol itself.

In this tutorial we will implement a simple websocket server endpoint in a Java EE environment and also the respective client-side infrastructure for sending and receiving data.

This tutorial considers the following environment:

  1. Ubuntu 12.04
  2. JDK 1.7.0.21
  3. Glassfish 4.0
Note: WebSockets support was introduced in Java EE 7
已有 2 人翻译此段
我来翻译

2. WebSocket server endpoint

Let's define a Java EE websocket server endpoint:

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");
  }
}
As you may have already noticed we are importing several classes from javax.websocket package.

@ServerEndpoint annotation is used at type level and defines the current class as a websocket server endpoint. The value used in this annotation represents the URL where the endpoint will be listening for client connections.

onOpen and onClose methods are annotated with @OnOpen and @OnClose respectively. These annotations are almost self-explanatory: They define which methods will be called upon a new client connection and disconnection.

Method onMessage is annotated with @OnMessage. This annotation defines which method will be called when a new message is received from the client. Note that this method may be defined with an optional parameter of type javax.websocket.Session (in our case the session parameter). If this parameter is defined the container will inject the session that is associated with the current client that sent the message being handled.

In our case we are just writing the client message content to the standard output. Then we proceed to send a message to the client followed by 3 test messages with a 5 second interval. Finally we send a final message to the client.

已有 1 人翻译此段
我来翻译

3. Client side

Now we need to write the client-side of our websocket test application:

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>
This is a simple test page that contains the JavaScript that will create a websocket connection to out websocket server endpoint.

onOpen method will be called when we establish a connection with the server endpoint.

onError method is called when an error occurs during client-server communication.

onMessage method will be called when a message is received from the server. In our case we are just appending the messages received from the server to the DOM.

We connect to the websocket server endpoint by using the construct new WebSocket() and passing the endpoint URL:

ws://localhost:8080/byteslounge/websocket

已有 1 人翻译此段
我来翻译

4. Testing

We may now test our application by accessing the testing page:

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

We will see the Connection established message as expected:

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

Now as soon as we press the button we will send the initial message to the server through the websocket and receive the subsequent test messages sent by the server:

Messages sent by the server and received by the client

已有 1 人翻译此段
我来翻译

5. WebSockets Handshake

The TCP connection between the client and the server is established after the occurrence of a handshake over the HTTP protocol. It's easy to observe the handshake by using some HTTP traffic debugger. As soon as we create the WebSocket instance in the client the following request and respective server response will occur:

Note: we will only include HTTP headers that are relevant to the websockets handshake

Request:

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

Response:

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

Note that the client is requesting the protocol to be upgraded to the WebSocket protocol by using Connection: Upgrade and Upgrade: websocket HTTP headers. The server response states that the client request was accepted and it will change protocol to WebSocket (using HTTP status code 101):

HTTP/1.1 101 Web Socket Protocol Handshake

6. Downloadable sample

The example source code is available for download at the end of this page. The test was executed in Glassfish 4 (you will need a Java EE 7 compliant application server).

Download source code from this tutorial

已有 1 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 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请求。
具体怎么做的?
返回顶部
顶部