WebSocket起航 JavaScript客户端和Server通信
Message =>JSON => Move
客户端发给服务器总是Move server.send(JSON.stringify({row: row, column: column})); 服务端(Move move = TicTacToeServer.mapper.readValue(message, Move.class);)
服务端发给客户端总是Message session.getBasicRemote() .sendText(TicTacToeServer.mapper.writeValueAsString(message));
【javascript客户端】
1.创建websocket连接
// ws[s]://localhost/ticTacToe/${gameId}/${username}?action=${action}
server = new WebSocket('ws://' + window.location.host +
'<c:url value="/ticTacToe/${gameId}/${username}">'+
'<c:param name="action" value="${action}" /></c:url>');
//view = f(state)
server.onopen = function (event) {
modalWaitingBody
.text('Waiting on your opponent to join the game.');
modalWaiting.modal({keyboard: false, show: true});
};
【Server】
public void onOpen(Session session, @PathParam("gameId") long gameId,
@PathParam("username") String username)
{
TicTacToeGame ticTacToeGame = TicTacToeGame.getActiveGame(gameId);
//动作
List<String> actions = session.getRequestParameterMap().get("action");
if(actions != null && actions.size() == 1)
{
String action = actions.get(0);
if("start".equalsIgnoreCase(action))
{
Game game = new Game();//新建一个游戏
game.gameId = gameId;//路径参数
game.player1 = session;//一个玩家就是一个session
TicTacToeServer.games.put(gameId, game);//往内存数据库
}
else if("join".equalsIgnoreCase(action))
{
Game game = TicTacToeServer.games.get(gameId);//获得同一个游戏准备加入
game.player2 = session;//一个玩家就是一个session
game.ticTacToeGame = TicTacToeGame.startGame(gameId, username);//游戏里面p1在等,开始游戏
this.sendJsonMessage(game.player1, game,
new GameStartedMessage(game.ticTacToeGame));//服务器往客户端玩家发送消息
this.sendJsonMessage(game.player2, game,
new GameStartedMessage(game.ticTacToeGame));
}
}
}
2.【通信】客户端send 出去
move = function (row, column) {
if (!myTurn) {
modalErrorBody.text('It is not your turn yet!');
modalError.modal('show');
return;
}
if (server != null) {
//转换Object字面量 为json
server.send(JSON.stringify({row: row, column: column}));
$('#r' + row + 'c' + column).unbind('click')
.removeClass('game-cell-selectable')
.addClass('game-cell-player game-cell-taken');
toggleTurn(false);
} else {
modalErrorBody.text('Not connected to came server.');
modalError.modal('show');
}
};
【Server】发给客户端
@OnMessage
public void onMessage(Session session, String message,
@PathParam("gameId") long gameId)
{
Game game = TicTacToeServer.games.get(gameId);
boolean isPlayer1 = session == game.player1; try
{
//经过ObjectMapper 反序列化客户端的Message成服务端的Move
Move move = TicTacToeServer.mapper.readValue(message, Move.class);
game.ticTacToeGame.move(
isPlayer1 ? TicTacToeGame.Player.PLAYER1 :
TicTacToeGame.Player.PLAYER2,
move.getRow(),
move.getColumn()
);
//发回给客户端 json 消息
this.sendJsonMessage((isPlayer1 ? game.player2 : game.player1), game,
new OpponentMadeMoveMessage(move));
if(game.ticTacToeGame.isOver())
{
if(game.ticTacToeGame.isDraw())
{
this.sendJsonMessage(game.player1, game,
new GameIsDrawMessage());
this.sendJsonMessage(game.player2, game,
new GameIsDrawMessage());
}
else
{
boolean wasPlayer1 = game.ticTacToeGame.getWinner() ==
TicTacToeGame.Player.PLAYER1;
this.sendJsonMessage(game.player1, game,
new GameOverMessage(wasPlayer1));
this.sendJsonMessage(game.player2, game,
new GameOverMessage(!wasPlayer1));
}
game.player1.close();
game.player2.close();
}
}
catch(IOException e)
{
this.handleException(e, game);
}
}
接收服务器发的消息
server.onmessage = function (event) {
var message = JSON.parse(event.data);
if (message.action == 'gameStarted') {
if (message.game.player1 == username)
opponentUsername = message.game.player2;
else
opponentUsername = message.game.player1;
opponent.text(opponentUsername);
toggleTurn(message.game.nextMoveBy == username);
modalWaiting.modal('hide');
} else if (message.action == 'opponentMadeMove') {
$('#r' + message.move.row + 'c' + message.move.column)
.unbind('click')
.removeClass('game-cell-selectable')
.addClass('game-cell-opponent game-cell-taken');
toggleTurn(true);
} else if (message.action == 'gameOver') {
toggleTurn(false, 'Game Over!');
if (message.winner) {
modalGameOverBody.text('Congratulations, you won!');
} else {
modalGameOverBody.text('User "' + opponentUsername +
'" won the game.');
}
modalGameOver.modal('show');
} else if (message.action == 'gameIsDraw') {
toggleTurn(false, 'The game is a draw. ' +
'There is no winner.');
modalGameOverBody.text('The game ended in a draw. ' +
'Nobody wins!');
modalGameOver.modal('show');
} else if (message.action == 'gameForfeited') {
toggleTurn(false, 'Your opponent forfeited!');
modalGameOverBody.text('User "' + opponentUsername +
'" forfeited the game. You win!');
modalGameOver.modal('show');
}
};
【与websocket无关提供请求参数】【TicTacToeServlet(url、post变量、)和list.jsp(菜单)】
Servlet => list.jsp 发送attribute pendingGames(相当于qq游戏房间)
【list.jsp=>Servlet】关键代码
post({action: 'join', username: username, gameId: gameId});
var post = function(fields) {
//构造隐藏表单,仅为了doPost方法
var form = $('<form id="mapForm" method="post"></form>')
.attr({ action: url, style: 'display: none;' });
for(var key in fields) {
//字面量传进来 转化成隐藏域
if(fields.hasOwnProperty(key))
form.append($('<input type="hidden">').attr({
name: key, value: fields[key]
}));
}
$('body').append(form);
form.submit();
};
WebSocket起航 JavaScript客户端和Server通信的更多相关文章
- 第14章 添加JavaScript客户端 - Identity Server 4 中文文档(v1.0.0)
本快速入门将展示如何构建基于浏览器的JavaScript客户端应用程序(有时称为" SPA "). 用户将登录IdentityServer,使用IdentityServer发出的访 ...
- javascript客户端与服务器端通信
高性能的网络通信包括以下方面:选择正确的数据格式和与之匹配的传输技术. 一.数据格式 用于传输的数据格式有: 1)html,仅适用于特定场合,传输数据量大,不过它可以节省客户端的CPU周期, 2)XM ...
- WebSocket 开发模拟客户端与有游戏服务器通信
WebSocket 客户端测试功能 websocket是有标准的通信协议,在h2engine服务器引擎中继承了websocket通信协议,使用websocket通信协议的好处是很多语言或框架都内置了w ...
- 前端开发【第6篇:JavaScript客户端(浏览器)】
Web浏览器中的JavaScript 客户端JavaScript时间线 1.Web浏览器创建Document对象,并且开始解析web页面,解析HTML元素和它门的文本内容后添加Element对象和Te ...
- Java开发之使用websocket实现web客户端与服务器之间的实时通讯
使用websocket实现web客户端与服务器之间的实时通讯.以下是个简单的demo. 前端页面 <%@ page language="java" contentType=& ...
- SignalR的Javascript客户端API使用方式整理
SignalR的服务端提供了两种实现方式,分别是PersistentConnection和Hub,这两种方式的侧重点不同: PersistentConnection更接近于底层,编程接口比较简单,传输 ...
- 当使用母版页时JavaScript客户端获取服务器控件的Id
当使用MasterPage.UserControl等容器时,为了避免控件的重复命名,asp.net会自动将容器中的控件生成一个ClientID(Control Tree中的可生成,否则不会生成). J ...
- [C语言]一个很实用的服务端和客户端进行TCP通信的实例
本文给出一个很实用的服务端和客户端进行TCP通信的小例子.具体实现上非常简单,只是平时编写类似程序,具体步骤经常忘记,还要总是查,暂且将其记下来,方便以后参考. (1)客户端程序,编写一个文件clie ...
- rpc,客户端与NameNode通信的过程
远程过程:java进程.即一个java进程调用另外一个java进程中对象的方法. 调用方称作客户端(client),被调用方称作服务端(server).rpc的通信在java中表现为客户端去调用服务端 ...
随机推荐
- SHOI2008仙人掌图(tarjan+dp)
Solution 好题啊没的说. 本题需要求出仙人掌的直径,但仙人掌是一个带有简单环的一张图无法直接用树形dp求解,但它有一个好东西就是没有类似环套环的东西,所以我们在处理时就方便了一些. 思路:ta ...
- PHP使用自定义key实现对数据加密解密
// 加密 function encryptStr($str, $key){ $block = mcrypt_get_block_size('des', 'ecb'); $pad = $block - ...
- Java线程池中submit()和execute之间的区别?
一: submit()方法,可以提供Future < T > 类型的返回值. executor()方法,无返回值. execute无返回值 public void execute(Runn ...
- 跟着 underscore 学节流
更多内容请参考:我的新博客 在上一篇文章中,我们了解了为什么要限制事件的频繁触发,以及如何做限制: debounce 防抖 throttle 节流 上次已经说过防抖的实现了,今天主要来说一下节流的实现 ...
- Codeforces Round #525 (Div. 2)
Codeforces Round #525 (Div. 2) 哎,忍不住想吐槽一下,又要准备训练,又要做些无聊的事,弄得我都想退出了. 好好的训练不好么???? 只能做出两道水题,其实C题,感觉做出来 ...
- selenium自动化测试原理和设计的分享
昨天参加了公司的一个自动化测试的分享,有一些收获,记录一下. 1.主流的web端的UI自动化测试工具 基于浏览器API: selenium2.0,Watir(IE Driver) 基于JS 进行驱动: ...
- Android Studio项目引入外部库注意事项(zxing)
1.复制到app同级目录下,zxing: 2.在项目根目录下的settings.gradle下添加第三方库目录 4.在app/build.gradle下添加编译依赖 compile project(p ...
- 快速傅里叶变换(FFT)_转载
FFTFFT·Fast Fourier TransformationFast Fourier Transformation快速傅立叶变换 P3803 [模板]多项式乘法(FFT) 参考上文 首 ...
- 解析:为什么程序员应该有一台Mac个人电脑?
对于开发来讲,使用Mac电脑的好处,下面简单列举几个: 首先,macOS很安全和稳定,Mac 系统的底层是最原始的unix操作系统,很多大型的银行和军工企业都是这个操作系统,安全性很高,基本不需要安装 ...
- 使用SSH命令行传输文件到远程服务器
以前一直在windows下用SSH Secure Shell连接远程服务器,它自带了一个可视化的文件传输工具,跟ftp差不多 但是它也存在一个缺陷,不支持编码的选择,遇到utf8就自动乱码了,另外ma ...