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通信的更多相关文章

  1. 第14章 添加JavaScript客户端 - Identity Server 4 中文文档(v1.0.0)

    本快速入门将展示如何构建基于浏览器的JavaScript客户端应用程序(有时称为" SPA "). 用户将登录IdentityServer,使用IdentityServer发出的访 ...

  2. javascript客户端与服务器端通信

    高性能的网络通信包括以下方面:选择正确的数据格式和与之匹配的传输技术. 一.数据格式 用于传输的数据格式有: 1)html,仅适用于特定场合,传输数据量大,不过它可以节省客户端的CPU周期, 2)XM ...

  3. WebSocket 开发模拟客户端与有游戏服务器通信

    WebSocket 客户端测试功能 websocket是有标准的通信协议,在h2engine服务器引擎中继承了websocket通信协议,使用websocket通信协议的好处是很多语言或框架都内置了w ...

  4. 前端开发【第6篇:JavaScript客户端(浏览器)】

    Web浏览器中的JavaScript 客户端JavaScript时间线 1.Web浏览器创建Document对象,并且开始解析web页面,解析HTML元素和它门的文本内容后添加Element对象和Te ...

  5. Java开发之使用websocket实现web客户端与服务器之间的实时通讯

    使用websocket实现web客户端与服务器之间的实时通讯.以下是个简单的demo. 前端页面 <%@ page language="java" contentType=& ...

  6. SignalR的Javascript客户端API使用方式整理

    SignalR的服务端提供了两种实现方式,分别是PersistentConnection和Hub,这两种方式的侧重点不同: PersistentConnection更接近于底层,编程接口比较简单,传输 ...

  7. 当使用母版页时JavaScript客户端获取服务器控件的Id

    当使用MasterPage.UserControl等容器时,为了避免控件的重复命名,asp.net会自动将容器中的控件生成一个ClientID(Control Tree中的可生成,否则不会生成). J ...

  8. [C语言]一个很实用的服务端和客户端进行TCP通信的实例

    本文给出一个很实用的服务端和客户端进行TCP通信的小例子.具体实现上非常简单,只是平时编写类似程序,具体步骤经常忘记,还要总是查,暂且将其记下来,方便以后参考. (1)客户端程序,编写一个文件clie ...

  9. rpc,客户端与NameNode通信的过程

    远程过程:java进程.即一个java进程调用另外一个java进程中对象的方法. 调用方称作客户端(client),被调用方称作服务端(server).rpc的通信在java中表现为客户端去调用服务端 ...

随机推荐

  1. 杨辉三角 II

    题目描述 给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行. 在杨辉三角中,每个数是它左上方和右上方的数的和. 示例: 输入: 3 输出: [1,3,3,1] 贴出代码 class ...

  2. MYSQL timestamp NOT NULL插入NULL的报错问题

    1. 在开发两个数据库数据同步功能的时候,需要在本地搭建一个本地的数据库作为一个本地库,然后用于同步开发库中的数据.在插入的时候出现了一个问题. 问题描述: 我们每张表中都会存在一个create_ti ...

  3. QML-WebEngineView加载html(Echarts绘图)

    实现QML中运用webEngineView加载Echarts GitHub:八至 作者:狐狸家的鱼 本文链接:QML-WebEngineView加载Echarts 一.前言 Qt允许使用混合GUI创建 ...

  4. poj2054 Color a Tree

    神题.这题是巨毒瘤... 自己写真可谓是: 排空驭气奔如电,上天入地求之遍 上穷碧落下黄泉,两处茫茫皆不见 由于我们知道:不是树形时,不停选值最大的节点可以得到最小代价. 那么我们就能想出一个错误的贪 ...

  5. http 请求头和响应头

    客户端发送请求过程带着的数据: 1.请求地址 2.请求方式 3.请求头 request headers 4.请求参数 https://www.juhe.cn/ 130.... 1a2b....pei ...

  6. Autotools知识点

    最近研究了下glog使用autotools编译方法的脚本文件,略有所得 configure.ac AC_INIT初始化一些信息 Package Version ReportBug AC_CONFIG_ ...

  7. (链表 set) leetcode 817. Linked List Components

    We are given head, the head node of a linked list containing unique integer values. We are also give ...

  8. mysql体系结构和sql查询执行过程简析

    一: mysql体系结构 1)Connectors 不同语言与 SQL 的交互 2)Management Serveices & Utilities 系统管理和控制工具 备份和恢复的安全性,复 ...

  9. org.hibernate.MappingException: class com.itheima.domain.Customer.java not found while looking for property: cust_id at org.hibernate.internal.util.ReflectHelper.reflectedPropertyClass(ReflectHelper.

    我这次异常的出现时,没有配置逐渐生成策略.

  10. CodeForces5E 环转链,dp思想

    http://codeforces.com/problemset/problem/5/E 众所周知,在很久以前,在今天的 Berland 地区,居住着 Bindian 部落.他们的首都被 n 座山所环 ...