- 浏览: 253667 次
- 性别:
- 来自: 宁波
文章分类
最新评论
-
wangxiang243:
文件保存为utf8编码格式就可以了吧
java.util.Properties 乱码问题解决方案 -
uyiab:
真心感谢,之前搞了一套2.1.4的程序,一直发生这个问题,找了 ...
如何解决cocos2dx2.1.4回到前台后出现的黑屏现象 -
Tongqing-Qiu:
我用的Intellij IDEA集成的GIT工具,挺方便的。有 ...
git分支、合并的使用记录 -
nbtlxx:
...
三星s7572无法显示toast的问题解决 -
kouwoo:
这篇文章对我非常有用,谢谢
三星s7572无法显示toast的问题解决
上次简单介绍了Server的写法,这个类比较简单,主要的功能包括:
1. 初始化,包括玩家列表、游戏桌子列表
2. 接收手机客户端连接
3. 启动网络连接处理
今天主要介绍:网络通讯类和业务处理类
Network类:
主要负责:
1. 接收手机客户端的连接
按照协议读取数据后,添加到消息队列
此处需要处理同步问题
2. 取出消息队列,调用业务逻辑类进行处理
主要是根据消息的cmdType
3. 发送消息
依次读取发送消息队列的消息,
按照协议,依次将cmdType, playerId, msg.length, msg 发送到客户端
具体代码如下:
逻辑处理类LogicHandler.java
该类的主要功能
1. 去除消息队列的消息对象
2. 分析消息的cmdType
3. 然后分发给相应的消息处理方法进行处理
基本流程包括:
玩家注册:就是将玩家对象放入playerMap的哈希表待用
玩家坐下:根据发送过来的消息,更新桌子列表情况,然后返回消息
玩家请求开始:设置玩家的状态为开始,检查该游戏桌子的状态是否满足条件
满足的话,就开始游戏,并且调用相关的裁判类进行逻辑判断处理
玩家的棋子移动:根据具体的棋子坐标,更新裁判类的棋牌位置
其他还包括玩家退出、离开游戏等,目前还未完成。
详细查看代码:
注:很多代码参考了java项目全程实录
1. 初始化,包括玩家列表、游戏桌子列表
2. 接收手机客户端连接
3. 启动网络连接处理
今天主要介绍:网络通讯类和业务处理类
Network类:
主要负责:
1. 接收手机客户端的连接
按照协议读取数据后,添加到消息队列
此处需要处理同步问题
2. 取出消息队列,调用业务逻辑类进行处理
主要是根据消息的cmdType
3. 发送消息
依次读取发送消息队列的消息,
按照协议,依次将cmdType, playerId, msg.length, msg 发送到客户端
具体代码如下:
/** * */ package net.tuolian.newserver; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * @author sean * * @since 2009/06/17 * * 1. 构造方法 * 2. init, 获得输入输出流 * 3. 启动线程 * * 问题: 1.全部读取服务器数据到Byte数组后,如何区别各个位数的内容 * 2. 如果光读取一个cmdType,然后由相应的方法来读取内容 */ public class Network extends Thread { Socket socket; DataInputStream dis; DataOutputStream dos; public static List<Message> list = Collections.synchronizedList(new ArrayList<Message>()); //消息队列 /** * 构造函数 * 初始化 * @param socket */ public Network(Socket socket) { // TODO Auto-generated constructor stub this.socket = socket; init(); } LogicHandler logic; /** * 初始化,获得输入输出流 */ private void init() { // TODO Auto-generated method stub try { dis = new DataInputStream(socket.getInputStream()); dos = new DataOutputStream(socket.getOutputStream()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } logic = new LogicHandler(this); } /** * 接收数据 逻辑处理 */ public void run() { while (true) { // 接收客户端数据 recieveData(); // 逻辑处理 // handleLogic(); logic.logicProcess(); // 发送数据 sendData(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 接收来自客户端的数据 * 重构: * 本方法只是负责读取数据 * 同时打包成msg, 放入msgList * * @return */ private void recieveData() { // TODO Auto-generated method stub int len = 0; try { len = dis.available(); if(len <= 0){ return; } int cmdType = dis.readInt(); int playerId = dis.readInt(); len = dis.readInt(); byte[] data = new byte[len]; dis.read(data); String str = new String(data); //构建消息对象,放入队列 Message msg = new Message(cmdType, str); if(playerId != 0){ msg.setPlayerId(playerId); } else{ //如果playerId==0, 则表示属于未注册的新客户端,设置为1 msg.setPlayerId(1); } list.add(msg); } catch (IOException e) { // TODO Auto-generated catch block close(); System.out.println("网络连接错误"); // e.printStackTrace(); } } /** * 负责根据消息的内容,大包成需要的格式,一次写入输出流 * * @param msg * @param player */ private void packMessage(Message msg, Player player) { // TODO 将消息打包成msg进行发送 try { player.getOutputStream().writeInt(msg.getCmdType()); System.out.println("Server: send cmdType: " + msg.getCmdType()); player.getOutputStream().writeInt(msg.getPlayerId()); System.out.println("Server: send playerId: " + msg.getPlayerId()); player.getOutputStream().writeInt( msg.getMessage().getBytes().length); player.getOutputStream().write(msg.getMessage().getBytes()); System.out.println("Server: send cmdType: " + msg.getMessage()); System.out.println("send data ok"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 发送数据到客户端 获取player中包含的输出流通道 */ private void sendData() { // TODO Auto-generated method stub if (Server.playerMap.isEmpty()) { return; } Iterator it = Server.playerMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry<Integer, Player> entry = (Entry<Integer, Player>) it .next(); Player player = entry.getValue(); if (player == null) { return; } /** * 如果数据不为空,则发送队列中的数据到客户端 */ if (!player.data.isEmpty()) { Message msg = (Message) player.data.pop(); packMessage(msg, player); } } } /** * 关闭连接 */ private void close() { try { dis.close(); dos.close(); socket.close(); } catch (Exception e) { } } }
逻辑处理类LogicHandler.java
该类的主要功能
1. 去除消息队列的消息对象
2. 分析消息的cmdType
3. 然后分发给相应的消息处理方法进行处理
基本流程包括:
玩家注册:就是将玩家对象放入playerMap的哈希表待用
玩家坐下:根据发送过来的消息,更新桌子列表情况,然后返回消息
玩家请求开始:设置玩家的状态为开始,检查该游戏桌子的状态是否满足条件
满足的话,就开始游戏,并且调用相关的裁判类进行逻辑判断处理
玩家的棋子移动:根据具体的棋子坐标,更新裁判类的棋牌位置
其他还包括玩家退出、离开游戏等,目前还未完成。
详细查看代码:
/** * */ package net.tuolian.newserver; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * @author sean * * */ public class LogicHandler { private List list = null; private Network network; public LogicHandler(Network network){ this.network = network; list = network.list; } /** * */ public void logicProcess(){ if( list.size() <= 0){ return; } Message msg = (Message) list.remove(0); if( msg == null){ return; } int cmdType = msg.getCmdType(); switch (cmdType) { case Message.REGISTER_REQ: handleRegister(msg); break; case Message.TAKE_REQ: handleTake(msg); break; case Message.START_REQ: handleStart(msg); break; case Message.MOVE_REQ: handleMove(msg); break; case Message.EXIT_REQ: handleExit(msg); break; case Message.EXITGAME_REQ: handleExitGame(msg); break; default: break; } } /** * 初次登陆用户的注册逻辑 * 将好友放入playerMap保存 * 设置playerId * */ private void handleRegister(Message msg) { Server.counter++; System.out.println("counter: " + Server.counter); Player player = null; player = new Player(); player.setID(Server.counter); player.setOutputStream(network.dos); if(player != null){ Server.playerMap.put(new Integer(Server.counter), player); //发送桌子信息到客户端 sendDesksInfo(player); } } /** * 处理客户端坐下的动作 */ private void handleTake(Message msg) { String message = null; Player player = null; int playerId = msg.getPlayerId(); System.out.println("handleTake playerid " + playerId); player = Server.playerMap.get(playerId); message = msg.getMessage(); System.out.println("Server recieve take msg: " + message); try { int index1 = message.indexOf(","); int index2 = message.indexOf(",", index1 + 1); int dindex = Integer .parseInt(message.substring(index1 + 1, index2)); int pindex = Integer.parseInt(message.substring(index2 + 1)); if (dindex < Server.DESKNUM && dindex >= 0) { if (Server.desks[dindex].isEmpty(pindex)) { Server.desks[dindex].setPlayer(pindex, player); player.setDesk(Server.desks[dindex]); sendMessage(Message.UPDATEDESK_RESP, player, "takeseat"); updateClientsDesk(dindex); } } } catch (Exception exc) { } } /** * 遍历所有玩家,更新桌子的玩家情况 * * @param dindex */ private void updateClientsDesk(int dindex) { // TODO Auto-generated method stub Iterator it = Server.playerMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry<Integer, Player> entry = (Entry<Integer, Player>) it .next(); Player player = (Player) entry.getValue(); updateDesks(player, dindex); } } /** * 更新具体桌号的玩家情况 * * @param player * @param dindex */ private void updateDesks(Player player, int dindex) { // TODO Auto-generated method stub String message = "updatedesk," + dindex; String str = ""; for (int i = 0; i < Server.desks[dindex].getPlayersCounter(); i++) { if (i == 0) { if (Server.desks[dindex].isEmpty(i)) { str = "0"; } else { str = "1"; } } else { if (Server.desks[dindex].isEmpty(i)) { str = "0"; } else { str = "1"; } } message = message + str; } sendMessage(Message.UPDATEDESK_RESP, player, message); System.out.println("Server send updateDesk message"); } /** * 处理开始游戏的状态 */ private void handleStart(Message msg) { // TODO Auto-generated method stub int playerId = msg.getPlayerId(); Player player = Server.playerMap.get(playerId); // 开始处理游戏开始的逻辑 player.start(); Desk desk1 = player.getDesk(); if (desk1.isReady()) { desk1.start(); } System.out.println("Server: handle start process ok"); } /** * 处理游戏中移动的业务逻辑 */ private void handleMove(Message msg) { Player player = null; int playerId = msg.getPlayerId(); String message1 = msg.getMessage(); System.out.println("server recieved move msg: " + message1); player = Server.playerMap.get(playerId); Desk desk = player.getDesk(); desk.moveChess(message1); } /** * 退出当前游戏,回到游戏大厅 * @param msg */ private void handleExit(net.tuolian.newserver.Message msg) { // TODO Auto-generated method stub } /** * 玩家退出当前游戏的逻辑处理 */ private void handleExitGame(Message msg) { // TODO 玩家退出当前游戏的逻辑处理, 得到玩家的桌子,玩家初始化,桌子去掉玩家、玩家列表去掉玩家,更新桌子 int playerId = msg.getPlayerId(); Player player = Server.playerMap.get(playerId); Desk desk = player.getDesk(); desk.removePlayer(player); Server.playerMap.remove(player); player = null; updateClientsDesk(desk.getID()); } /** * 发送桌子的数据信息 * * @param player */ private void sendDesksInfo(Player player) { // TODO Auto-generated method stub int cmdType = Message.DESKS_RESP; String message = "desks," + Server.DESKNUM; for (int i = 0; i < Server.DESKNUM; i++) { String str = ""; for (int j = 0; j < Server.desks[i].getPlayersCounter(); j++) { if (j == 0) { if (Server.desks[i].isEmpty(j)) str = "0"; else str = "1"; } else { if (Server.desks[i].isEmpty(j)) str = str + ",0"; else str = str + ",1"; } } message = message + ":" + str; } sendMessage(cmdType, player, message); } /** * 发送消息 * 将速度打包成msg,放入队列中等待发送 * @param cmdType * @param player * @param message */ private void sendMessage(int cmdType, Player player, String message) { // TODO Auto-generated method stub Message msg = new Message(cmdType, message); msg.setPlayerId(player.getID()); player.data.push(msg); } }
注:很多代码参考了java项目全程实录
发表评论
-
cocos2dx斗地主产品错误修复过程
2013-12-27 10:57 1343一个多星期没有写新的东西了。下面内容是最近修复的一个bug的过 ... -
eclipse adt 更新到22.3后R文件不能自动生成的解决
2013-12-16 14:05 1960上周六手痒,把android develop tools(ad ... -
如何解决cocos2dx2.1.4回到前台后出现的黑屏现象
2013-12-11 14:17 1986cocos2dx1.4引擎上开发的app。安装好点击打开运行。 ... -
手机游戏UI的初步设计
2010-09-03 13:32 1412主要工作参考无花的代码,再次感谢。 1. Part.java ... -
手机游戏引擎框架的初步想法
2010-09-03 13:25 1340一直想重构下手机游戏客户端的引擎 主要思路: 1. Main. ... -
ioserver的学习体会
2010-08-31 18:21 1174ioserver的学习体会 1. config. 设置地址(s ... -
MMORPG开发入门
2009-07-25 23:37 1868原著:Radu Privantu 翻译:pAnic ... -
手机网络象棋开发(7): 架构优化规划
2009-06-27 12:50 1200主要是针对Server进行架构的优化 1. 采用最新NIO机 ... -
手机网络象棋开发(6):Mycanvas及共用类介绍
2009-06-27 11:44 1357MyCancas类比较复杂 主要 ... -
手机网络象棋开发(5):客户端Game类、网络通讯类NetClient介绍
2009-06-27 11:34 3121Game.java 继承midlet * 游戏程序的入口 ... -
手机网络象棋开发(4):核心类Desk, Umpire介绍
2009-06-27 10:55 1301今天介绍下Desk、Umpire类 Desk这个类非常重要, ... -
手机网络象棋开发(3):公用类介绍
2009-06-26 17:54 1224共用类主要包括Player,Queue,Message 这些 ... -
手机网络象棋开发(1): 服务器类Server介绍
2009-06-24 22:56 1365为了更好的理解手机网络游戏的架构和开发技巧,本人在他人手机网络 ... -
参考学习封装Queue队列,先进先出
2009-06-06 11:56 2105最近由于项目需求,参考有关的代码,学习封装了一个队列 主要技术 ... -
手机网络游戏的几个特点
2009-05-19 09:14 1714本人觉得手机网络游戏 ... -
手机游戏网络休闲游戏开发思路
2009-05-19 08:53 1781项目初步设想:开发一个基于目前pc游戏平台的手机休闲游戏,将符 ...
相关推荐
2. **棋局逻辑**:源码会详细描述象棋规则,如棋子的移动规则、吃子规则、将军和将死的判断、以及各种特殊棋局(如长将、五七炮等)的处理。这部分可能使用算法和数据结构来实现,如棋盘的状态表示、棋子的坐标系统...
总的来说,《PHP开发典型模块大全》中的网络象棋游戏模块是一个综合性的实例,涵盖了PHP的很多重要知识点,包括但不限于游戏逻辑编程、用户交互、网络通信、数据库操作、安全性以及代码架构设计。通过研究这个模块,...
在这个网络象棋项目中,Java用于编写游戏逻辑、用户界面以及网络通信模块。 2. **TCP通信**: 传输控制协议(TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在本项目中,TCP被用来确保游戏数据在...
2. 网络通信模块:负责客户端与服务器之间的数据交换,包括连接建立、消息编码解码、错误处理等。 3. 用户界面:显示棋盘、棋子,处理用户输入,提供反馈信息。 4. 多线程处理:服务器端可能需要多线程来处理多个...
在IT领域,开发一款网络对战象棋游戏不仅考验编程技能,还涉及到网络通信、图形界面设计、人工智能等多个方面的知识。本篇文章将详细探讨基于VC++实现的象棋游戏源代码,帮助读者深入理解其背后的原理与技术。 首先...
这个项目中的“中国象棋网络对弈游戏”可能包含以下几个部分:游戏逻辑模块(处理象棋规则)、网络通信模块(实现客户端与服务器的套接字通信)、用户界面模块(展示游戏画面和交互)以及可能的多线程或并发处理模块...
文件“网络象棋VB.net 3.5复盘功能(4-22)”很可能包含了整个项目的源代码,包括界面设计、游戏逻辑、网络通信模块以及复盘功能的实现。通过深入研究这些代码,开发者不仅可以学习到如何使用VB2005.NET进行网络编程,...
理想情况下,应该将网络通信逻辑、游戏逻辑和用户界面分别封装在不同的类或模块中,以保持代码的清晰和可维护性。例如,可以创建一个`ChessServer`类负责处理网络通信,一个`ChessGame`类处理游戏规则,以及一个`...
【标题】"基于Python的网络版中国象棋"是一个创新性的项目,它将传统的中国象棋游戏与现代的网络通信技术相结合,使玩家能够在局域网内通过网络进行双人对战。这个项目的核心在于利用Python编程语言实现游戏逻辑、...
2. 游戏逻辑模块:负责处理棋局规则,如合法移动判断、胜负检测等。 3. 事件处理模块:处理用户输入和游戏状态的更新。 4. 可能存在AI模块:如果包含AI对弈,会有实现算法的代码。 5. 网络模块:如果支持在线对战,...
2. **网络通信模块**:包括连接建立、数据发送和接收、错误处理等功能,可能使用异步I/O或线程池来提高并发性能。 3. **用户界面**:MFC的CDialog和CButton等类用于构建用户界面,事件驱动的编程模式使用户交互变得...
3. **网络通信**:网络版中国象棋需要实现客户端与服务器之间的数据传输,易语言提供了网络模块,允许开发者编写网络应用。这涉及到TCP/IP协议、连接建立、数据包发送和接收等技术。 4. **多线程处理**:为了让游戏...
3. **Networking**:包含网络通信模块,负责客户端和服务器间的连接、数据交换。 4. **Server Management**:服务器端代码,处理客户端连接、请求处理、状态同步等。 5. **Database Integration**:数据库操作接口,...
2. **网络编程**:网络中国象棋涉及网络通信,需要理解TCP/IP协议,学会使用Java的Socket编程来建立客户端和服务器之间的连接,进行数据传输。 3. **多线程设计**: - **服务器端**:服务器端需要管理多个客户端的...
2. **多线程**:由于游戏需要同时处理用户的输入和网络通信,因此需要多线程技术来避免阻塞。可能使用Thread、Task或者异步编程模型(async/await)来保证程序的响应性和流畅性。 3. **对象序列化**:为了在网络上...
QT的核心特性包括强大的图形渲染能力、丰富的UI组件库、多平台支持以及高效的网络通信功能,这些都使得QT成为开发网络版中国象棋的理想选择。 在这个项目中,开发者首先需要理解QT的事件驱动模型,这是构建用户界面...
【Java编写中国象棋手机网络游戏】是一个基于J2ME(Java Micro Edition)和Servlet技术的项目,主要目标是实现一个可以在移动设备上运行的在线中国象棋游戏平台。以下是这个项目涉及的关键知识点: 1. **J2ME**:...
一个完整的中国象棋程序通常包含以下几个主要部分:用户界面(UI)、游戏逻辑、网络通信模块(针对网络版)以及可能的AI(人工智能)模块。在VB中,这些可以通过类和对象来实现,每个部分都可以看作是一个独立的实体...
总之,这个基于Delphi的中国象棋网络版源码涵盖了游戏逻辑、用户界面、网络通信等多个方面的编程技术。通过深入分析和学习,不仅可以提升Delphi编程技能,也能深入了解游戏开发的全貌,对于任何希望从事游戏开发或者...
通过这些文件,我们可以看出该程序的设计思路:使用C++语言编写,采用面向对象的方法,将界面显示、游戏逻辑、网络通信等模块化,使得代码结构清晰,易于维护。同时,集成MIDI支持提升了用户体验,而设置对话框则让...