📄 selectandread.java
字号:
package zsw_mmorpg.server;import zsw_mmorpg.common.*;import zsw_mmorpg.server.controller.GameController;import zsw_mmorpg.server.controller.ShenzhouController;import zsw_mmorpg.log.zsw_out;import java.nio.*;import java.nio.channels.*;import java.io.*;import java.util.*;import org.apache.log4j.Logger;/** * SelectAndRead.java * * handles reading from all clients using a Selector * and hands off events to the appropriatae GameControllers * * @author <a href="mailto:shiwei@raymobile.com">朱世伟</a> * @version 1.0 */public class SelectAndRead extends Thread { /** log4j 日志 */ private static Logger log = Logger.getLogger("SelectAndRead"); private LinkedList newClients; private Selector selector; private GameServer gameServer; public SelectAndRead (GameServer gameServer){ this.gameServer = gameServer; newClients = new LinkedList(); } /** * 添加新连接 */ public void addNewClient(SocketChannel clientChannel) { synchronized (newClients) { newClients.addLast(clientChannel); } selector.wakeup(); } /** * 一直循环并检查新连接 */ public void run () { try { selector = Selector.open(); while (true) { select(); checkNewConnections(); try { Thread.sleep(30); } catch (InterruptedException e) {} } } catch (IOException e) { log.fatal("exception while opening Selector", e); } } /** * 检查新连接 */ private void checkNewConnections() { synchronized(newClients) { while (newClients.size() > 0) { try { SocketChannel clientChannel = (SocketChannel)newClients.removeFirst(); clientChannel.configureBlocking( false); clientChannel.register( selector, SelectionKey.OP_READ, new Attachment()); } catch (ClosedChannelException cce) { log.error("channel closed", cce); } catch (IOException ioe) { log.error("ioexception on clientChannel", ioe); } } } } /** * 主要函数之一,用来读通道数据, * 读到缓存里面,并把游戏事 * 件从数据包中解析出来 */ private void select() { try { selector.select(); Set readyKeys = selector.selectedKeys(); Iterator i = readyKeys.iterator(); while (i.hasNext()) { SelectionKey key = (SelectionKey) i.next(); i.remove(); SocketChannel channel = (SocketChannel) key.channel(); Attachment attachment = (Attachment) key.attachment(); try { // read long nbytes = channel.read(attachment.readBuff); // check for end if (nbytes == -1) { System.out.println("disconnect: " + channel.socket().getInetAddress() + ", end-of-stream"); channel.close();// System.out.println("channel.close();"); } byte[] array = new byte[0]; int start = 0, end = 0; if (attachment.readBuff.hasArray()) { array = attachment.readBuff.array(); end = attachment.readBuff.position(); } System.out.println("read array:"); //zsw NIOUtils.printHexValue(array, start, end); // 检查完整事件 try { if (attachment.readBuff.position() >= attachment.HEADER_SIZE) { attachment.readBuff.flip(); // 读缓存里,多个事件 while(attachment.eventReady()) { GameEvent event = getEvent(attachment); delegateEvent(event, channel); attachment.reset(); } // 准备再读 attachment.readBuff.compact(); } } catch (IllegalArgumentException e) { log.error("illegal argument exception", e); } } catch (IOException ioe) { System.out.println("IOException during read(), closing channel:" + channel.socket().getInetAddress()); channel.close();// System.out.println("channel.close();"); } } } catch (IOException ioe2) { System.out.println("IOException during select(): " + ioe2.getMessage()); } catch (Exception e) { log.error("exception during select()", e); } } /** * 从缓存里读事件 */ private GameEvent getEvent(Attachment attachment) { GameEvent event = null; ByteBuffer bb = ByteBuffer.wrap(attachment.payload); bb.order(ByteOrder.LITTLE_ENDIAN); GameController gc = gameServer.getGameController("RPS"); if (gc == null) { return null; } event = gc.createGameEvent(); event.read(bb); return event; } /** * 处理事件 */ private void delegateEvent(GameEvent event, SocketChannel channel) { if (event == null) { log.error("delegateEvent error ,GameServer.handleEvent() : game event is null"); return; } GameController gc = gameServer.getGameController("RPS"); if (gc == null) { log.error("delegateEvent error ,No GameController for gameName: " + event.getGameName()); return; } String pid = event.getPlayerId(); Player p = GameServer.getPlayerById(pid); if ((p != null)) { //当前玩家在线 if (p.getChannel() != channel) { //通道还不一样// log.warn("player is on a new channel, must be reconnect."); GameServer.getPlayerById("GM").setChannel(channel); //用GM帐号保存该连接 p.setPlayer_logged(true); } } else { // first time p = gc.createPlayer(); p.setPlayerId(event.getPlayerId()); p.setChannel(channel); p.setPlayer_logged(false); GameServer.addPlayer(p); log.debug("delegate event, new player created and channel set, player:" + p.getPlayerId() + ", channel: " + channel); } gc.handleEvent(event); p.setPlayer_online_flag(true); //在线 }}// SelectAndRead
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -