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. 解决忘记mysql中的root用户密码问题

    如果忘了数据库中的root密码,无法登陆mysql. 解决步骤: 1. 使用“--skip-grant-tables”启动数据库 ~]#systemctl stop mysql ~]#mysqld_s ...

  2. UVALive - 4225(贪心)

    题目链接:https://vjudge.net/contest/244167#problem/F 题目: Given any integer base b ≥ 2, it is well known ...

  3. 牛客练习赛31 D神器大师泰兹瑞与威穆

    双链表搞完了 #include<bits/stdc++.h> using namespace std; #define maxn 1000005 int tot,bac[maxn],fa[ ...

  4. A1142. Maximal Clique

    A clique is a subset of vertices of an undirected graph such that every two distinct vertices in the ...

  5. A1065. A+B and C (64bit)

    Given three integers A, B and C in [-263, 263], you are supposed to tell whether A+B > C. Input S ...

  6. bzoj1497 最大获利(最大权闭合子图)

    题目链接 思路 对于每个中转站向\(T\)连一条权值为建这个中转站代价的边.割掉这条边表示会建这个中转站. 对于每个人向他的两个中转站连一条权值为\(INF\)的边.然后从\(S\)向这个人连一条权值 ...

  7. T4模版 mysql

    MysqlDbhelper.ttinclude <#@ assembly name="System.Core"#> <#@ assembly name=" ...

  8. vue学习(1)

    前置的准备学习: ES6简单语法: 1.let和const 2.模板字符串 3.箭头函数 4.对象的单体模式 5.es6的面向对象 6.模块化 1.let和const <script type= ...

  9. python config.ini的应用

    config.ini文件的结构是以下这样的:结构是"[ ]"之下是一个section,一部分一部分的结构.以下有三个section,分别为section0,section1,sec ...

  10. 【知名的3D造型设计软件】犀牛 Rhinoceros 5.5.2 for Mac

    [简介] 今天和大家分享最新的3D设计软件 犀牛 Rhinoceros for Mac 5.5.2 版本,支持中文界面,这是一款Mac上知名的3D造型软件,犀牛可以广泛地应用于三维动画制作.工业制造. ...