习WebSocket一(WebSocket初识)[转]

http://www.cnblogs.com/wgp13x/p/3812579.html

Java EE 7 去年刚刚发布了JSR356规范,使得WebSocket的Java API得到了统一,Tomcat从7.0.47开始支持JSR356,这样一来写WebSocket的时候,所用的代码都是可以一样的。今天终于体验了一把Tomcat发布的WebSocket,用着很爽,下面把这一历程分享给大家。

关键词:WebSocket, Tomcat

前提:使用Tomcat7.0.47,Firefox25.0.0.5046



首先Tomcat7.0.47自带WebSocket的示例程序,有两种版本,一种是使用注解(annotation API)的方式,另一种是继承javax.websocket.Endpoint类(programmatic API)。

先启动一下,看看效果。有四个example:Echo(回音)、Chat(聊天)、Multiplayer snake(多人蛇游戏)、Multiplayer drawboard(多人画板游戏)。

1、Echo

回音很简单,就是你输入什么,服务器给你返回什么。

界面效果? 服务端代码

打开一个页面,首先点击Connect,保证连接到Websocket,

再在输入框里输入"I am angel1!",

点击Echo message,可以看到下面框里输入Sent和Received信息。

我们看一下它的代码是怎么实现的。
可以看出,在OnMessage处就是简单的通过传来的Session得到某一客户端,
再向其发出同样的消息。


@ServerEndpoint("/websocket/echoAnnotation")

public class EchoAnnotation {

@OnMessage

public void echoTextMessage(Session session, String msg, boolean last) {

try {

if (session.isOpen()) {

session.getBasicRemote().sendText(msg, last);

}

} catch (IOException e) {

try {

session.close();

} catch (IOException e1) {

// Ignore

}

}

}

@OnMessage

public void echoBinaryMessage(Session session, ByteBuffer bb,

boolean last) {

try {

if (session.isOpen()) {

session.getBasicRemote().sendBinary(bb, last);

}

} catch (IOException e) {

try {

session.close();

} catch (IOException e1) {

// Ignore

}

}

}
}

2、Chat

这里的聊天室跟群聊是同一个效果,不能一对一单聊。

界面效果? 服务端代码
打开第一个页面,它会告诉你,你已经加入聊天了。
分析代码,就是一个新连接,会自动实例化一个ChatAnnotation,
这些ChatAnnotation对象共用同一些属性,
最重要的就是Set<ChatAnnotation> conncetions,
在OnOpen处把自身实例加入到conncetions中,并广播消息。
广播消息,是轮循conncetions并发送消息。

在界面输入对话框处输入文字,回车,消息就会发送到服务端。
就会传入到服务端某ChatAnnotation的OnMessage处,
然后把收到的消息与自身名称拼接后,再广播出去。
这下在线的客户端就都能够收到消息了。

第一个页面:

第二个页面:


@ServerEndpoint(value = "/websocket/chat")

public class ChatAnnotation {

private static final String GUEST_PREFIX = "Guest";

private static final AtomicInteger connectionIds = new AtomicInteger(0);

private static final Set<ChatAnnotation> connections =

new CopyOnWriteArraySet<ChatAnnotation>();

private final String nickname;

private Session session;

public ChatAnnotation() {

nickname = GUEST_PREFIX + connectionIds.getAndIncrement();

}

@OnOpen

public void start(Session session) {

this.session = session;

connections.add(this);

String message = String.format("* %s %s", nickname, "has joined.");

broadcast(message);

}

@OnClose

public void end() {

connections.remove(this);

String message = String.format("* %s %s",

nickname, "has disconnected.");

broadcast(message);

}

@OnMessage

public void incoming(String message) {

// Never trust the client

String filteredMessage = String.format("%s: %s",

nickname, HTMLFilter.filter(message.toString()));

broadcast(filteredMessage);

}

private static void broadcast(String msg) {

for (ChatAnnotation client : connections) {

try {

client.session.getBasicRemote().sendText(msg);

} catch (IOException e) {

connections.remove(client);

try {

client.session.close();

} catch (IOException e1) {

// Ignore

}

String message = String.format("* %s %s",

client.nickname, "has been disconnected.");

broadcast(message);

}

}

}

}

3、Multiplayer snake

这是一个多人在线小游戏,客户端通过操作上下左右键指挥自己的蛇,如果碰到别的蛇就死掉。还是一样,在服务端,对每个连接都维护一条蛇,有一个总的逻辑代码处理这些蛇,每条蛇再有各自的状态,向每个连接的客户发送消息。


@ServerEndpoint(value = "/websocket/snake")

public class SnakeAnnotation {

public static final int PLAYFIELD_WIDTH = 640;

public static final int PLAYFIELD_HEIGHT = 480;

public static final int GRID_SIZE = 10;

private static final AtomicInteger snakeIds = new AtomicInteger(0);

private static final Random random = new Random();

private final int id;

private Snake snake;


public static String getRandomHexColor() {

float hue = random.nextFloat();

// sat between 0.1 and 0.3

float saturation = (random.nextInt(2000) + 1000) / 10000f;

float luminance = 0.9f;

Color color = Color.getHSBColor(hue, saturation, luminance);

return ‘#‘ + Integer.toHexString(

(color.getRGB() & 0xffffff) | 0x1000000).substring(1);

}

public static Location getRandomLocation() {

int x = roundByGridSize(random.nextInt(PLAYFIELD_WIDTH));

int y = roundByGridSize(random.nextInt(PLAYFIELD_HEIGHT));

return new Location(x, y);

}

private static int roundByGridSize(int value) {

value = value + (GRID_SIZE / 2);

value = value / GRID_SIZE;

value = value * GRID_SIZE;

return value;

}

public SnakeAnnotation() {

this.id = snakeIds.getAndIncrement();

}


@OnOpen

public void onOpen(Session session) {

this.snake = new Snake(id, session);

SnakeTimer.addSnake(snake);

StringBuilder sb = new StringBuilder();

for (Iterator<Snake> iterator = SnakeTimer.getSnakes().iterator();

iterator.hasNext();) {

Snake snake = iterator.next();

sb.append(String.format("{id: %d, color: ‘%s‘}",

Integer.valueOf(snake.getId()), snake.getHexColor()));

if (iterator.hasNext()) {

sb.append(‘,‘);

}

}

SnakeTimer.broadcast(String.format("{‘type‘: ‘join‘,‘data‘:[%s]}",

sb.toString()));

}

@OnMessage

public void onTextMessage(String message) {

if ("west".equals(message)) {

snake.setDirection(Direction.WEST);

} else if ("north".equals(message)) {

snake.setDirection(Direction.NORTH);

} else if ("east".equals(message)) {

snake.setDirection(Direction.EAST);

} else if ("south".equals(message)) {

snake.setDirection(Direction.SOUTH);

}

}

@OnClose

public void onClose() {

SnakeTimer.removeSnake(snake);

SnakeTimer.broadcast(String.format("{‘type‘: ‘leave‘, ‘id‘: %d}",

Integer.valueOf(id)));

}

@OnError

public void onError(Throwable t) throws Throwable {

// Most likely cause is a user closing their browser. Check to see if

// the root cause is EOF and if it is ignore it.

// Protect against infinite loops.

int count = 0;

Throwable root = t;

while (root.getCause() != null && count < 20) {

root = root.getCause();

count ++;

}

if (root instanceof EOFException) {

// Assume this is triggered by the user closing their browser and

// ignore it.

} else {

throw t;

}

}
}

4、自写客户端

Multiplayer drawboard就不分析了,在Firefox25.0.0.5046上一直loading。下面探讨一下,Java客户端的编写。

界面和ClientEndpoit?
入口代码

下面是调用了echoAnnotation的websocket的客户端与服务端交互过程。

同样是客户端发给服务端一个消息,服务端收到后发给客户端,

客户端收到后显示出来。

客户端代码也很简单,没有什么逻辑,只管把接收的打印出来就行了。

需要注意的是,需要引用的jar包只在Java EE 7中包含。

包括javax.websocket-api.jar、tyrus-client.jar、

tyrus-container-grizzly.jar、tyrus-core.jar、

tyrus-websocket-core.jar、tyrus-spi.jar、tyrus-server.jar、

nucleus-grizzly-all.jar

同样的也可以调用其它的websocket,比如chat...使用起来非常方便。

@ClientEndpoint

public class MyClient {

@OnOpen

public void onOpen(Session session) {

}

@OnMessage

public void onMessage(String message) {

System.out.println("Client onMessage: " + message);

}

@OnClose

public void onClose() {

}

}


public class Main {

private static String uri = "ws://localhost/examples/websocket/echoAnnotation";

private static Session session;

private void start() {

WebSocketContainer container = null;

try {

container = ContainerProvider.getWebSocketContainer();

} catch (Exception ex) {

System.out.println("error" + ex);

}

try {

URI r = URI.create(uri);

session = container.connectToServer(MyClient.class, r);

} catch (DeploymentException | IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

Main client = new Main();

client.start();

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

String input = "";

try {

do {

input = br.readLine();

if (!input.equals("exit"))

client.session.getBasicRemote().sendText(input);

} while (!input.equals("exit"));

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

这样以来,从功能少的说,搭建向手机、客户端推送消息的服务器是非常简单的;从功能多的说,以后搭建安全的、扩展性好的、性能超群的游戏服务器,比如QQ斗地主游戏、泡泡卡丁车游戏,在线聊天服务器,也是简单的。http://www.cnblogs.com/wgp13x/p/3800030.html  这是我之前的局域网多人对战飞行棋的实现,因为它是C#局域网版本的,故没有用到WebSocket技术。

时间: 2024-08-01 20:13:40

习WebSocket一(WebSocket初识)[转]的相关文章

【Html5 WebSocket】WebSocket事件

<HTML5 WebSocket权威指南>学习笔记&2 上一篇:[Html5 WebSocket]WebSocket构造函数 WebSocket事件 WebSocket编程遵循异步编程模式,只要WebSocket的连接已打开,应用程序就开始监听事件.客户端不需要主动轮询服务器获取更多信息.下面是WebSocket对象的四个不同的监听器: open message error close 上述四个事件同所有的Web API一样,可以通过on<事件名称>处理对象属性监听这些事件

【HTML5 WebSocket】WebSocket对象特性和方法

<HTML5 WebSocket权威指南>学习笔记&3 WebSocket方法的对象特性 1. WebSocket方法 a. send方法 send方法用于在WebSocket连接建立后,客户端向服务端发送消息.可分为发送两种消息,一种是普通文本信息,一种是二进制数据.需注意的是,send方法必须在连接建立以后才能使用,也就是在onopen里使用才不会出错. 发送普通消息 这个比较简单,在上一篇学习WebSocket事件时就用到了,只需要send(message)即可. 发送二进制数据

Python自动化3.0-------学习之路-------模块初识!

模块初识 Python的强大之处在于他有非常丰富和强大的标准库和第三方库,几乎你想实现的任何功能都有相应的Python库支持,以后的课程中会深入讲解常用到的各种库,现在,我们先来象征性的学2个简单的. sys #!/usr/bin/env python# -*- coding: utf-8 -*- import sys print(sys.argv) #输出$ python test.py helo world['test.py', 'helo', 'world'] #把执行脚本时传递的参数获取

初识html5 WebSocket

1.  WebSocket概念 WebSocket是HTML5开始提供的一种Client与Server间进行全双工(full-duplex)通讯的网络技术 双工(duplex),指二台通讯设备之间,允许有双向的资料传输 Client和Server通过WebSocket Protocol建立连接后,双方可以互传数据并且双方都可以关闭此连接 2. HTTP概念 HTTP Protocol是无状态协议的,Client和Server通过HTTP Protocol建立连接后,将采用"request-res

【HTML5】websocket 初识

什么是WebSocket API? WebSocket API是下一代客户端-服务器的异步通信方法.该通信取代了单个的TCP套接字,使用ws或wss协议,可用于任意的客户端和服务器程序.WebSocket目前由W3C进行标准化.WebSocket已经受到Firefox 4.Chrome 4.Opera 10.70以及Safari 5等浏览器的支持. WebSocket API最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息.WebSocket并不限于以Ajax(或XHR

初识WebSocket协议

1.什么是WebSocket协议 RFC6455文档的表述如下: The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code. The security model used for

认识HTML5的WebSocket

认识HTML5的WebSocket 在HTML5规范中,我最喜欢的Web技术就是正迅速变得流行的WebSocket API.WebSocket提供了一个受欢迎的技术,以替代我们过去几年一直在用的Ajax技术.这个新的API提供了一个方法,从客户端使用简单的语法有效地推动消息到服务器.让我们看一看HTML5的WebSocket API:它可用于客户端.服务器端.而且有一个优秀的第三方API,名为Socket.IO. 一.什么是WebSocket API? WebSocket API是下一代客户端-

tomcat支持的websocket服务

首发:个人博客 在tomcat7之后的版本,写个websocket服务程序非常容易--如以下代码所示,当客户端建立了一个连接并发送了一些什么内容到服务器,服务器将每隔两秒返回一个字符串"world".之所以演示每两秒返回一次是为了说明这是长连接而不是短连接. import java.io.IOException; import javax.websocket.OnMessage;import javax.websocket.Session;import javax.websocket.

使用 HTML5 WebSocket 构建实时 Web 应用

作为下一代的 Web 标准,HTML5 拥有许多引人注目的新特性,如 Canvas.本地存储.多媒体编程接口.WebSocket 等等.这其中有"Web 的 TCP "之称的 WebSocket 格外吸引开发人员的注意.WebSocket 的出现使得浏览器提供对 Socket 的支持成为可能,从而在浏览器和服务器之间提供了一个基于 TCP 连接的双向通道.Web 开发人员可以非常方便地使用 WebSocket 构建实时 web 应用,开发人员的手中从此又多了一柄神兵利器.本文首先介绍

WebSocket实战之——携带Token验证绑定clientId到uid(微信)

HTML代码:通过为. <!DOCTYPE> <html> <meta charset="utf-8"/> <title>WebSocket Test</title> <script src="http://cdn.bootcss.com/jquery/2.1.3/jquery.min.js" type="text/javascript"></script> &l