Jetty WebSocket API使用

Jetty提供了功能更强的WebSocket API,使用一个公共的核心API供WebSockets的服务端和client使用。

他是一个基于WebSocket消息的事件驱动的API。

WebSocket事件

每一个WebSocket都能接收多种事件:

On Connect Event

表示WebSocket升级成功,WebSocket如今打开。

 你将收到一个org.eclipse.jetty.websocket.api.Session对象,相应这个Open事件的session。

 为通常的WebSocket,应该紧紧抓住这个Session,并使用它与Remote Endpoint进行交流。

 假设为无状态(Stateless)WebSockets,这个Session将被传递到它出现的每个事件,同意你使用一个WebSocket的1个实例为多个Remote Endpoint提供服务。

On Close Event

表示WebSocket已经关闭。

 每一个Close事件将有一个状态码(Status Code)(和一个可选的Closure Reason Message)。

 一个通常的WebSocket终止将经历一个关闭握手,Local Endpoint和Remote Endpoint都会发送一个Close帧表示连接被关闭。

 本地WebSocket能够通过发送一个Close帧到Remote Endpoint表示希望关闭,可是Remote Endpoint能继续发送信息直到它送一个Close帧为止。这被称之为半开(Half-Open)连接,注意一旦Local Endpoint发送了Close帧后,它将不能再发送不论什么WebSocket信息。

 在一个异常的终止中,比如一个连接断开或者超时,底层连接将不经历Close Handshake就被终止,这也将导致一个On Close Event(和可能伴随一个On Error Event)。

On Error Event

假设一个错误出现,在实现期间,WebSocket将通过这个事件被通知。

On Message Event

表示一个完整的信息被收到,准备被你的WebSocket处理。

 这能是一个(UTF8)TEXT信息或者一个原始的BINARY信息。

WebSocket Session

Session对象能被用于:

获取WebSocket的状态

连接状态(打开或者关闭)

  1. if(session.isOpen()) {
  2. // send message
  3. }

连接是安全的吗。

  1. if(session.isSecure()) {
  2. // connection is using 'wss://'
  3. }

在升级请求和响应中的是什么。

  1. UpgradeRequest req = session.getUpgradeRequest();
  2. String channelName = req.getParameterMap().get("channelName");
  3.  
  4. UpgradeRespons resp = session.getUpgradeResponse();
  5. String subprotocol = resp.getAcceptedSubProtocol();

本地和远端地址是什么。

  1. InetSocketAddress remoteAddr = session.getRemoteAddress();

配置策略

获取和设置空暇超时时间。

  1. session.setIdleTimeout(2000); // 2 second timeout

获取和设置最大信息长度。

  1. session.setMaximumMessageSize(64*1024); // accept messages up to 64k, fail if larger

发送信息到Remote Endpoint

Session的最重要的特征是获取org.eclipse.jetty.websocket.api.RemoteEndpoint

使用RemoteEndpoint,你能选择发送TEXT或者BINARY Websocket信息,或者WebSocket PING和PONG控制帧。

堵塞式发送信息

其实大部分调用都是堵塞式的,直到发送完毕(或者抛出一个异常)才返回。

  1. 实例1 发送二进制信息(堵塞)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Blocking Send of a BINARY message to remote endpoint
  5. ByteBuffer buf = ByteBuffer.wrap(new byte[] { 0x11, 0x22, 0x33, 0x44 });
  6. try
  7. {
  8. remote.sendBytes(buf);
  9. }
  10. catch (IOException e)
  11. {
  12. e.printStackTrace(System.err);
  13. }

怎么使用RemoteEndpoint送一个简单的二进制信息。这将堵塞直到信息被发送完毕,假设不能发送信息可能将抛出一个IOException。

  1. 实例2 发送文本信息(堵塞)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Blocking Send of a TEXT message to remote endpoint
  5. try
  6. {
  7. remote.sendString("Hello World");
  8. }
  9. catch (IOException e)
  10. {
  11. e.printStackTrace(System.err);
  12. }

怎么使用RemoteEndpoint发送文本信息。这将堵塞直到信息发送,假设不能发送信息可能将抛出一个IOException。

发送部分信息

假设你有一个大的信息须要被发送,而且想分多次发送,每次一部分,你能使用RemoteEndpoint发送部分信息的方法。仅须要确保你最后发送一个完毕发送的信息(isLast == true)

  1. 实例3 发送部分二进制信息(堵塞)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Blocking Send of a BINARY message to remote endpoint
  5. // Part 1
  6. ByteBuffer buf1 = ByteBuffer.wrap(new byte[] { 0x11, 0x22 });
  7. // Part 2 (last part)
  8. ByteBuffer buf2 = ByteBuffer.wrap(new byte[] { 0x33, 0x44 });
  9. try
  10. {
  11. remote.sendPartialBytes(buf1,false);
  12. remote.sendPartialBytes(buf2,true); // isLast is true
  13. }
  14. catch (IOException e)
  15. {
  16. e.printStackTrace(System.err);
  17. }

怎么分两次发送一个二进制信息,使用在RemoteEndpoint中的部分信息支持方法。这将堵塞直到每次信息发送完毕,假设不能发送信息可能抛出一个IOException。

  1. 实例4 发送部分文本信息(堵塞)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Blocking Send of a TEXT message to remote endpoint
  5. String part1 = "Hello";
  6. String part2 = " World";
  7. try
  8. {
  9. remote.sendPartialString(part1,false);
  10. remote.sendPartialString(part2,true); // last part
  11. }
  12. catch (IOException e)
  13. {
  14. e.printStackTrace(System.err);
  15. }

怎么通过两次发送一个文本信息,使用在RemoteEndpoint中的部分信息支持方法。这将堵塞直到每次信息发送完毕,假设不能发送信息可能抛出一个IOException。

发送Ping/Pong控制帧

你也能使用RemoteEndpoint发送Ping和Pong控制帧。

  1. 实例5 发送Ping控制帧(堵塞)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Blocking Send of a PING to remote endpoint
  5. String data = "You There?";
  6. ByteBuffer payload = ByteBuffer.wrap(data.getBytes());
  7. try
  8. {
  9. remote.sendPing(payload);
  10. }
  11. catch (IOException e)
  12. {
  13. e.printStackTrace(System.err);
  14. }

怎么发送一个Ping控制帧,附带一个负载“You There?”(作为一个字节数组负载到达Remote Endpoint)。这将堵塞直到信息发送完毕,假设不能发送Ping帧,可能抛出一个IOException。

  1. 实例6 Pong控制帧(堵塞)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Blocking Send of a PONG to remote endpoint
  5. String data = "Yup, I'm here";
  6. ByteBuffer payload = ByteBuffer.wrap(data.getBytes());
  7. try
  8. {
  9. remote.sendPong(payload);
  10. }
  11. catch (IOException e)
  12. {
  13. e.printStackTrace(System.err);
  14. }

怎么发送一个Pong控制帧,附带一个"Yup I'm here"负载(作为一个字节数组负载到达Remote Endpoint)。这将堵塞直到信息被发送,假设不能发送Pong帧,可能抛出一个IOException。

为了正确的使用Pong帧,你应该返回你在Ping帧中收到的相同的字节数组数据。

异步发送信息

也存在来年改革异步发送信息的方法可用:

 1)RemoteEndpoint.sendBytesByFuture(字节信息)

 2)RemoteEndpoint.sendStringByFuture(字符串信息)

两个方法都返回一个Future<Void>,使用标准java.util.concurrent.Future行为,能被用于測试信息发送的成功和失败。

  1. 实例7 送二进制信息(异步)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Async Send of a BINARY message to remote endpoint
  5. ByteBuffer buf = ByteBuffer.wrap(new byte[] { 0x11, 0x22, 0x33, 0x44 });
  6. remote.sendBytesByFuture(buf);

怎么使用RemoteEndpoint发送一个简单的二进制信息。这个信息将被放入发送队列,你将不知道发送成功或者失败。

  1. 实例8 发送二进制信息(异步,等待直到成功)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Async Send of a BINARY message to remote endpoint
  5. ByteBuffer buf = ByteBuffer.wrap(new byte[] { 0x11, 0x22, 0x33, 0x44 });
  6. try
  7. {
  8. Future<Void> fut = remote.sendBytesByFuture(buf);
  9. // wait for completion (forever)
  10. fut.get();
  11. }
  12. catch (ExecutionException | InterruptedException e)
  13. {
  14. // Send failed
  15. e.printStackTrace();
  16. }

怎么使用RemoteEndpoint发送一个简单的二进制信息,追踪Future<Void>以确定发送成功还是失败。

  1. 实例9 送二进制信息(异步,发送超时)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Async Send of a BINARY message to remote endpoint
  5. ByteBuffer buf = ByteBuffer.wrap(new byte[] { 0x11, 0x22, 0x33, 0x44 });
  6. Future<Void> fut = null;
  7. try
  8. {
  9. fut = remote.sendBytesByFuture(buf);
  10. // wait for completion (timeout)
  11. fut.get(2,TimeUnit.SECONDS);
  12. }
  13. catch (ExecutionException | InterruptedException e)
  14. {
  15. // Send failed
  16. e.printStackTrace();
  17. }
  18. catch (TimeoutException e)
  19. {
  20. // timeout
  21. e.printStackTrace();
  22. if (fut != null)
  23. {
  24. // cancel the message
  25. fut.cancel(true);
  26. }
  27. }

怎么使用RemoteEndpoint发送一个简单的二进制信息,追踪Future<Void>并等待一个有限的时间,假设时间超限则取消该信息。

  1. 实例10 发送文本信息(异步)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Async Send of a TEXT message to remote endpoint
  5. remote.sendStringByFuture("Hello World");
  6.  
  7. 怎么使用RemoteEndpoint发送一个简单的文本信息。这个信息将被放到输出队列中,可是你将不知道发送成功还是失败。
  8.  
  9. 实例11 发送文本信息(异步,等待直到成功)
  10. RemoteEndpoint remote = session.getRemote();
  11.  
  12. // Async Send of a TEXT message to remote endpoint
  13. try
  14. {
  15. Future<Void> fut = remote.sendStringByFuture("Hello World");
  16. // wait for completion (forever)
  17. fut.get();
  18. }
  19. catch (ExecutionException | InterruptedException e)
  20. {
  21. // Send failed
  22. e.printStackTrace();
  23. }

怎么使用RemoteEndpoint发送一个简单的二进制信息,追踪Future<Void>以直到发送成功还是失败。

  1. 实例12 发送文本信息(异步,发送超时)
  2. RemoteEndpoint remote = session.getRemote();
  3.  
  4. // Async Send of a TEXT message to remote endpoint
  5. Future<Void> fut = null;
  6. try
  7. {
  8. fut = remote.sendStringByFuture("Hello World");
  9. // wait for completion (timeout)
  10. fut.get(2,TimeUnit.SECONDS);
  11. }
  12. catch (ExecutionException | InterruptedException e)
  13. {
  14. // Send failed
  15. e.printStackTrace();
  16. }
  17. catch (TimeoutException e)
  18. {
  19. // timeout
  20. e.printStackTrace();
  21. if (fut != null)
  22. {
  23. // cancel the message
  24. fut.cancel(true);
  25. }
  26. }

怎么使用RemoteEndpoint发送一个简单的二进制信息,追踪Future<Void>并等待有限的时间,假设超时则取消。

使用WebSocket凝视

WebSocket的最主要的形式是一个被Jetty WebSocket API提供的用凝视标记的POJO。

  1. 实例13 AnnotatedEchoSocket.java
  2. package examples.echo;
  3.  
  4. import org.eclipse.jetty.websocket.api.Session;
  5. import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
  6. import org.eclipse.jetty.websocket.api.annotations.WebSocket;
  7.  
  8. /**
  9. * Example EchoSocket using Annotations.
  10. */
  11. @WebSocket(maxTextMessageSize = 64 * 1024)
  12. public class AnnotatedEchoSocket {
  13.  
  14. @OnWebSocketMessage
  15. public void onText(Session session, String message) {
  16. if (session.isOpen()) {
  17. System.out.printf("Echoing back message [%s]%n", message);
  18. session.getRemote().sendString(message, null);
  19. }
  20. }
  21. }

上面的样例是一个简单的WebSocket回送端点,将回送全部它收到的文本信息。

这个实现使用了一个无状态的方法,因此对每一个出现的事件Session都会被传递到Message处理方法中。这将同意你在同多个port交互时能够重用AnnotatedEchoSocket的单实例。

你可用的凝视例如以下:

@WebSocket

一个必须的类级别的凝视。

标记这个POJO作为一个WebSocket。

类必须不是abstract,且是public。

@OnWebSocketConnect

一个可选的方法级别的凝视。

标记一个在类中的方法作为On Connect事件的接收者。

方法必须是public,且不是abstract,返回void,而且有且仅有一个Session參数。

@OnWebSocketClose

一个可选的方法级的凝视。

标记一个在类中的方法作为On Close事件的接收者。

方法标签必须是public,不是abstract,而且返回void。

方法的參数包含:

 1)Session(可选)

 2)int closeCode(必须)

 3)String closeReason(必须)

@OnWebSocketMessage

一个可选的方法级凝视。

标记在类中的2个方法作为接收On Message事件的接收者。

方法标签必须是public,不是abstract,而且返回void。

为文本信息的方法參数包含:

 1)Session(可选)

 2)String text(必须)

为二进制信息的方法參数包含:

 1)Session(可选)

 2)byte buf[](必须)

 3)int offset(必须)

 4)int length(必须)

@OnWebSocketError

一个可选的方法级凝视。

标记一个类中的方法作为Error事件的接收者。

方法标签必须是public,不是abstract,而且返回void。

方法參数包含:

 1)Session(可选)

 2)Throwable cause(必须)

@OnWebSocketFrame

一个可选的方法级凝视。

标记一个类中的方法作为Frame事件的接收者。

方法标签必须是public,不是abstract,而且返回void。

方法參数包含:

 1)Session(可选)

 2)Frame(必须)

收到的Frame将在这种方法上被通知,然后被Jetty处理,可能导致还有一个事件,比如On Close,或者On Message。对Frame的改变将不被Jetty看到。

用WebSocketListener

一个WebSocket的基本形式是使用org.eclipse.jetty.websocket.api.WebSocketListener处理收到的事件。

  1. 实例14 ListenerEchoSocket.java
  2. package examples.echo;
  3.  
  4. import org.eclipse.jetty.websocket.api.Session;
  5. import org.eclipse.jetty.websocket.api.WebSocketListener;
  6.  
  7. /**
  8. * Example EchoSocket using Listener.
  9. */
  10. public class ListenerEchoSocket implements WebSocketListener {
  11.  
  12. private Session outbound;
  13.  
  14. @Override
  15. public void onWebSocketBinary(byte[] payload, int offset, int len) {
  16. }
  17.  
  18. @Override
  19. public void onWebSocketClose(int statusCode, String reason) {
  20. this.outbound = null;
  21. }
  22.  
  23. @Override
  24. public void onWebSocketConnect(Session session) {
  25. this.outbound = session;
  26. }
  27.  
  28. @Override
  29. public void onWebSocketError(Throwable cause) {
  30. cause.printStackTrace(System.err);
  31. }
  32.  
  33. @Override
  34. public void onWebSocketText(String message) {
  35. if ((outbound != null) && (outbound.isOpen())) {
  36. System.out.printf("Echoing back message [%s]%n", message);
  37. outbound.getRemote().sendString(message, null);
  38. }
  39. }
  40. }

假设listener做了太多的工作,你能使用WebSocketAdapter取代。

使用WebSocketAdapter

WebSocketListener的适配器。

  1. 实例15 AdapterEchoSocket.java
  2. package examples.echo;
  3.  
  4. import java.io.IOException;
  5. import org.eclipse.jetty.websocket.api.WebSocketAdapter;
  6.  
  7. /**
  8. * Example EchoSocket using Adapter.
  9. */
  10. public class AdapterEchoSocket extends WebSocketAdapter {
  11.  
  12. @Override
  13. public void onWebSocketText(String message) {
  14. if (isConnected()) {
  15. try {
  16. System.out.printf("Echoing back message [%s]%n", message);
  17. getRemote().sendString(message);
  18. } catch (IOException e) {
  19. e.printStackTrace(System.err);
  20. }
  21. }
  22. }
  23. }

这个类比WebSocketListener跟为便利,并提供了实用的方法检查Session的状态。

Jetty WebSocket Server API

Jetty通过WebSocketServlet和servlet桥接的使用,提供了将WebSocket端点到Servlet路径的相应。

内在地,Jetty管理HTTP升级到WebSocket,而且从一个HTTP连接移植到一个WebSocket连接。

这仅仅有当执行在Jetty容器内部时才工作。

Jetty WebSocketServlet

为了通过WebSocketServlet相应你的WebSocket到一个指定的路径,你将须要扩展org.eclipse.jetty.websocket.servlet.WebSocketServlet并指定什么WebSocket对象应该被创建。

  1. 实例16 MyEchoServlet.java
  2. package examples;
  3.  
  4. import javax.servlet.annotation.WebServlet;
  5. import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
  6. import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
  7.  
  8. @SuppressWarnings("serial")
  9. @WebServlet(name = "MyEcho WebSocket Servlet", urlPatterns = { "/echo" })
  10. public class MyEchoServlet extends WebSocketServlet {
  11.  
  12. @Override
  13. public void configure(WebSocketServletFactory factory) {
  14. factory.getPolicy().setIdleTimeout(10000);
  15. factory.register(MyEchoSocket.class);
  16. }
  17. }

这个样例将创建一个Sevlet,通过@WebServlet注解匹配到Servlet路径"/echo"(或者你能在你的web应用的WEB-INF/web.xml中手动的配置),当收到HTTP升级请求时将创建MyEchoSocket实例。

WebSocketServlet.configure(WebSocketServletFactory factory)是为你的WebSocket指定配置的地方。在这个样例中,我们指定一个10s的空暇超时,并注冊MyEchoSocket,即当收到请求时我们想创建的WebSocket类,使用默认的WebSocketCreator创建。

使用WebSocketCreator

全部WebSocket都是通过你注冊到WebSocketServletFactory的WebSocketCreator创建的。

默认,WebSocketServletFactory是一个简单的WebSocketCreator,能创建一个单例的WebSocket对象。 使用WebSocketCreator.register(Class<?> websocket)告诉WebSocketServletFactory应该实例化哪个类(确保它有一个默认的构造器)。

假设你有更复杂的创建场景,你能够提供你自己的WebSocketCreator,基于在UpgradeRequest对象中出现的信息创建的WebSocket。

  1. 实例17 MyAdvancedEchoCreator.java
  2. package examples;
  3.  
  4. import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
  5. import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
  6. import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
  7.  
  8. public class MyAdvancedEchoCreator implements WebSocketCreator {
  9.  
  10. private MyBinaryEchoSocket binaryEcho;
  11.  
  12. private MyEchoSocket textEcho;
  13.  
  14. public MyAdvancedEchoCreator() {
  15. this.binaryEcho = new MyBinaryEchoSocket();
  16. this.textEcho = new MyEchoSocket();
  17. }
  18.  
  19. @Override
  20. public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp) {
  21. for (String subprotocol : req.getSubProtocols()) {
  22. if ("binary".equals(subprotocol)) {
  23. resp.setAcceptedSubProtocol(subprotocol);
  24. return binaryEcho;
  25. }
  26. if ("text".equals(subprotocol)) {
  27. resp.setAcceptedSubProtocol(subprotocol);
  28. return textEcho;
  29. }
  30. }
  31. return null;
  32. }
  33. }

这儿我们展示了一个WebSocketCreator,将利用来自请求的WebSocket子协议信息决定什么类型的WebSocket应该被创建。

  1. 实例18 MyAdvancedEchoServlet.java
  2. package examples;
  3.  
  4. import javax.servlet.annotation.WebServlet;
  5. import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
  6. import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
  7.  
  8. @SuppressWarnings("serial")
  9. @WebServlet(name = "MyAdvanced Echo WebSocket Servlet", urlPatterns = { "/advecho" })
  10. public class MyAdvancedEchoServlet extends WebSocketServlet {
  11.  
  12. @Override
  13. public void configure(WebSocketServletFactory factory) {
  14. factory.getPolicy().setIdleTimeout(10000);
  15. factory.setCreator(new MyAdvancedEchoCreator());
  16. }
  17. }

当你想要一个定制的WebSocketCreator时,使用WebSocketServletFactory.setCreator(WebSocketCreator creator),然后WebSocketServletFactory将为全部在这个servlet上收到的Upgrade请求用你的创造器。

一个WebSocketCreator还能够用于:

 1)控制WebSocket子协议的选择;

 2)履行不论什么你觉得重要的WebSocket源;

 3)从输入的请求获取HTTP头;

 4)获取Servlet HttpSession对象(假设它存在);

 5)指定一个响应状态码和原因;

假设你不想接收这个请求,简单的从WebSocketCreator.createWebSocket(UpgradeRequest req, UpgradeResponse resp)返回null。

Jetty WebSocket Client API

Jetty也提供了一个Jetty WebSocket Client库,为了更easy的与WebSocket服务端交互。

为了在你自己的Java项目上使用Jetty WebSocket Client,你将须要以下的maven配置:

  1. <dependency>
  2. <groupId>org.eclipse.jetty.websocket</groupId>
  3. <artifactId>websocket-client</artifactId>
  4. <version>${project.version}</version>
  5. </dependency>

WebSocketClient

为了使用WebSocketClient,你将须要连接一个WebSocket对象实例到一个指定的目标WebSocket URI。

  1. 实例19 SimpleEchoClient.java
  2. package examples;
  3.  
  4. import java.net.URI;
  5. import java.util.concurrent.TimeUnit;
  6. import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
  7. import org.eclipse.jetty.websocket.client.WebSocketClient;
  8.  
  9. /**
  10. * Example of a simple Echo Client.
  11. */
  12. public class SimpleEchoClient {
  13.  
  14. public static void main(String[] args) {
  15. String destUri = "ws://echo.websocket.org";
  16. if (args.length > 0) {
  17. destUri = args[0];
  18. }
  19. WebSocketClient client = new WebSocketClient();
  20. SimpleEchoSocket socket = new SimpleEchoSocket();
  21. try {
  22. client.start();
  23. URI echoUri = new URI(destUri);
  24. ClientUpgradeRequest request = new ClientUpgradeRequest();
  25. client.connect(socket, echoUri, request);
  26. System.out.printf("Connecting to : %s%n", echoUri);
  27. socket.awaitClose(5, TimeUnit.SECONDS);
  28. } catch (Throwable t) {
  29. t.printStackTrace();
  30. } finally {
  31. try {
  32. client.stop();
  33. } catch (Exception e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }
  38. }

上面的样例连接到一个远端WebSocket服务端,而且连接后使用一个SimpleEchoSocket履行在websocket上的处理逻辑,等待socket关闭。

  1. 实例20 SimpleEchoSocket.java
  2. package examples;
  3.  
  4. import java.util.concurrent.CountDownLatch;
  5. import java.util.concurrent.Future;
  6. import java.util.concurrent.TimeUnit;
  7. import org.eclipse.jetty.websocket.api.Session;
  8. import org.eclipse.jetty.websocket.api.StatusCode;
  9. import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
  10. import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
  11. import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
  12. import org.eclipse.jetty.websocket.api.annotations.WebSocket;
  13.  
  14. /**
  15. * Basic Echo Client Socket
  16. */
  17. @WebSocket(maxTextMessageSize = 64 * 1024)
  18. public class SimpleEchoSocket {
  19.  
  20. private final CountDownLatch closeLatch;
  21.  
  22. @SuppressWarnings("unused")
  23. private Session session;
  24.  
  25. public SimpleEchoSocket() {
  26. this.closeLatch = new CountDownLatch(1);
  27. }
  28.  
  29. public boolean awaitClose(int duration, TimeUnit unit) throws InterruptedException {
  30. return this.closeLatch.await(duration, unit);
  31. }
  32.  
  33. @OnWebSocketClose
  34. public void onClose(int statusCode, String reason) {
  35. System.out.printf("Connection closed: %d - %s%n", statusCode, reason);
  36. this.session = null;
  37. this.closeLatch.countDown();
  38. }
  39.  
  40. @OnWebSocketConnect
  41. public void onConnect(Session session) {
  42. System.out.printf("Got connect: %s%n", session);
  43. this.session = session;
  44. try {
  45. Future<Void> fut;
  46. fut = session.getRemote().sendStringByFuture("Hello");
  47. fut.get(2, TimeUnit.SECONDS);
  48. fut = session.getRemote().sendStringByFuture("Thanks for the conversation.");
  49. fut.get(2, TimeUnit.SECONDS);
  50. session.close(StatusCode.NORMAL, "I'm done");
  51. } catch (Throwable t) {
  52. t.printStackTrace();
  53. }
  54. }
  55.  
  56. @OnWebSocketMessage
  57. public void onMessage(String msg) {
  58. System.out.printf("Got msg: %s%n", msg);
  59. }
  60. }

当SimpleEchoSocket连接成功后,它发送2个文本信息,然后关闭socket。

onMessage(String msg)收到来自远端WebSocket的响应,并输出他们到控制台。

Jetty开发指导:Jetty Websocket API的更多相关文章

  1. Jetty开发指导:WebSocket介绍

    WebSocket是一个新的基于HTTP的双向通讯的协议. 它是基于低级别的框架协议.使用UTF-8 TEXT或者BINARY格式传递信息. 在WebSocket中的单个信息能够是不论什么长度(然而底 ...

  2. Jetty开发指导:HTTP Client

    介绍 Jetty HTTP client模块提供易用的API.工具类和一个高性能.异步的实现来运行HTTP和HTTPS请求. Jetty HTTP client模块要求Java版本号1.7或者更高,J ...

  3. Jetty开发指导:框架

    Spring设置 你能嵌入Jetty到你的项目中,也能够使用差点儿全部的IoC类型框架,包含Spring.假设全部你想做的是在你的Spring中设置Jetty Server,那么以下的xml片段能够作 ...

  4. Jetty:开发指导Handlers

    Rewrite Handler RewriteHandler匹配一个基于该请求的规则集合,然后根据匹配规则的变更请求. 最常见的要求是改写URI.但不限于:规则可以被配置为重定向响应.设置cookie ...

  5. Jetty使用教程(四:24-27)—Jetty开发指南

    二十四.处理器(Handler ) 24.1 编写一个常用的Handler Jetty的Handler组件用来处理接收到的请求. 很多使用者不需要编写Jetty的Handler ,而是通过使用Serv ...

  6. Jetty使用教程(四:23)—Jetty开发指南

    二十三.Maven和Jetty 这一章节将说明如何通过Maven管理Jetty和使用Jetty的Maven插件. 23.1 使用Maven Apache Maven是一个款软件项目管理工具.基于项目对 ...

  7. Jetty使用教程(四:21-22)—Jetty开发指南

    二十一.嵌入式开发 21.1 Jetty嵌入式开发HelloWorld 本章节将提供一些教程,通过Jetty API快速开发嵌入式代码 21.1.1 下载Jetty的jar包 Jetty目前已经把所有 ...

  8. Jetty 开发指南: 嵌入式开发之HelloWorld

    Jetty 嵌入式之 HelloWorld 本节提供一个教程,演示如何快速开发针对Jetty API的嵌入式代码. 1. 下载 Jar 包 Jetty被分解为许多jar和依赖项,通过选择最小的jar集 ...

  9. Jetty 开发指南:Jetty 内嵌开发

    Jetty的口号是“不要在Jetty中部署你的应用程序,在你的应用程序中部署Jetty!” 这意味着,作为将应用程序捆绑为要部署在Jetty中的标准WAR的替代方案,Jetty旨在成为一个软件组件,可 ...

随机推荐

  1. 基于visual Studio2013解决面试题之0203栈实现

     题目

  2. UVA 565 565 Pizza Anyone? (深搜 +位运算)

      Pizza Anyone?  You are responsible for ordering a large pizza for you and your friends. Each of th ...

  3. uva 10069 Distinct Subsequences(高精度 + DP求解子串个数)

    题目连接:10069 - Distinct Subsequences 题目大意:给出两个字符串x (lenth < 10000), z (lenth < 100), 求在x中有多少个z. ...

  4. 14.2.5.1 Role of the .frm File for InnoDB Tables InnoDB .frm文件的作用

    14.2.5.1 Role of the .frm File for InnoDB Tables: 14.2.5.1 Role of the .frm File for InnoDB Tables I ...

  5. java面向对象下:JavaXML解析技术

    20.JavaXML解析技术: XML概述:        XML可扩展标记性语言,用于数据表达和数据传递. XML语法规则:        合法DTDXML:1.内部DTD(和XML一起):2.外部 ...

  6. Win7和VS2013上使用Intel的TBB

    源地址:http://www.th7.cn/system/win/201505/103966.shtml http://wenku.baidu.com/link?url=zH7vwmWltWF5R-9 ...

  7. Qt之VLFeat SLIC超像素分割(Cpp版)

    源地址:http://yongyuan.name/blog/vlfeat-slic-with-qt.html 近段时间学了点Qt,恰好前段时间用借助VLfeat以及OpenCV捣鼓了SLIC超像素分割 ...

  8. VC调试技巧

    Visual C++ 的 C 运行时刻函数库标识模板0xCD    已经分配的数据(alloCated Data)0xDD    已经释放的数据(Deleted Data)0xFD    被保护的数据 ...

  9. HDU 1242——Rescue(优先队列)

    题意: 一个天使a被关在迷宫里,她的很多小伙伴r打算去救她.求小伙伴就到她须要的最小时间.在迷宫里有守卫.打败守卫须要一个单位时间.假设碰到守卫必须要杀死他 思路: 天使仅仅有一个,她的小伙伴有非常多 ...

  10. ThinkPHP 关联模型(二十)

    原文:ThinkPHP 关联模型(二十) ThinkPHP关联模型 两表关联查询:Message 和  user  关联条件uid(参考手册:模型->关联模型) 步骤: 一:创建Message表 ...