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中表现为客户端去调用服务端 ...
随机推荐
- HDU46093-idiots
题目大意 给一堆边的长度,问从中随机选出三条边来能够组成三角形的概率. 题解 其实就是要求能够组成三角形的方案数.直接从三条边入手问题会很复杂,所以我们可以先求出f[x]表示随便选出两条边长度之和为x ...
- 20165223 week1测试查漏补缺
week1查漏补缺 经过第一周的学习后,在蓝墨云班课上做了一套31道题的小测试,下面是对测试题中遇到的错误的分析和总结: 一.背记题 不属于Java后继技术的是? Ptyhon Java后继技术有? ...
- string的基本用法
#include <iostream> #include<string> #include<vector> #include<algorithm> us ...
- Python中生成器generator和迭代器Iterator的使用方法
一.生成器 1. 生成器的定义 把所需要值得计算方法储存起来,不会先直接生成数值,而是等到什么时候使用什么时候生成,每次生成一个,减少计算机占用内存空间 2. 生成器的创建方式 第一种只要把一个列表生 ...
- 如何刻录cd音乐
用nero,选择cd,音乐光盘(第一个)可以添加入wav,MP3等.刻录即可.
- A1043. Is It a Binary Search Tree
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following propertie ...
- quartz 每天0点5分开始,以后每隔15分钟启动一次,23:50停止
quartz 每天0点5分开始,以后每隔15分钟启动一次,23:50停止,这个表达式怎么写? 5 用quartz做定时器,要求达到这样的效果每天0点5分开始,以后每隔15分钟启动一次,23:50停止不 ...
- NOIP 提高组 2014 飞扬的小鸟(记录结果再利用的DP)
传送门 https://www.cnblogs.com/violet-acmer/p/9937201.html 参考资料: [1]:https://www.luogu.org/blog/xxzh242 ...
- 序列化serialize与反序列化unserialize
有利于存储和传递value(除了resource类型外),却不会丢失其原有类型和结构. serialize序列化时会调用魔术方法__sleep(); unserialize反序列化时会调用魔术方法__ ...
- KVM安装启动虚拟机
KVM定制OpenStack云主机 如何定制化OpenStack云主机?从去年10月份刚开始接触OpenStack,到现在也有一年了.虽说目前只是停留在用它,对它的一些组件简单的了解,但谈到制作出一个 ...