今天实在百无聊赖的看着代码,实在是没有意思,项目还要等到下个月启动,突然发现项目中的设计模式@H_404_7@
挺有趣的,就翻出来看看。@H_404_7@
@H_404_7@
因为我们项目中的结构是客户端-服务端,cs结构的,然后他们之间的通信,是怎么回事情的呢?@H_404_7@
以前粗略的看了,主要是通过tcp\ip方式进行通信,但是至少概念中知道吧。今天就翻看一下server代码。@H_404_7@
@H_404_7@
先来了解一下什么是reactor设计模式,反应堆模式。@H_404_7@
@H_404_7@
高性能I/O设计模式 - Reactor
该设计模式用于派发/分离IO操作事件的,这里所谓的IO事件也就是诸如read/write 的IO操作,“派发\分离”就是将单独的IO事件通知到上层模块,Reactor用于同步IO。
Reactor设计模式中的要素如下:
Handles,也就是网络连接,文件句柄等。是事件源。
Synchronous Event Demultiplexer,同步事件的解复用(或者说派发),具体的比如select调用。比select更加高效的有linux下的epoll,freebsd下的kqueue以及windows下的iocp(IO Completion port)。
Initiation Dispatcher,注册、移除和分派事件处理句柄。
Event Handler,就是事件处理句柄。
结合上面的描述,给出来自参考资料[3]图片如下:
@H_404_7@
@H_404_7@
@H_404_7@
@H_404_7@
@H_404_7@
下面这个是项目中的类图:@H_404_7@
@H_404_7@
@H_404_7@
1.reactor 负责响应IO事件,一旦发生,广播到响应的TcpThreadPool,TcpThreadPool发送给响应的IHandleEvent实现类去处理。@H_404_7@
@H_404_7@
2. handler是非阻塞行为,同时负责将handlers与event事件绑定。@H_404_7@
@H_404_7@
这里是refactor的handEvent方法;@H_404_7@
@H_404_7@
@H_404_7@
public int handleEvent(long wtime) { PendingObj handler = null; while ( (handler = _pendingQueue.pop()) != null) { if (handler.handler == null) continue; switch (handler.type) { case ACP_TYPE: try { initServerChannel(handler); } catch (Exception e) { Debug.logout(Debug.ERROR,this,e); } break; case CON_TYPE: try { initClientChannel(handler); } catch (Exception e) { Debug.logout(Debug.ERROR,e); } break; default: try { updateSelectCol(handler); } catch (Exception e) { Debug.msg(Debug.ERROR,"updateSelectCol occur exception:",e.getMessage()); Debug.logout(Debug.ERROR,e); } break; } } // long cur = System.currentTimeMillis(); // long to = timequeue.earliestTime(); // long cal = to - cur; // if (wtime > cal) // wtime = cal; int num; this.wakenUp.set(false); try { if (wtime <= 0) num = selector.selectNow(); // no here,and not permit walking here,or else cpu 100% else num = selector.select(wtime); } catch (Exception e) { Debug.msg(Debug.ERROR,"selector occur exception:",e.getMessage()); Debug.logout(Debug.ERROR,e); return -1; } // timequeue.dispatchHandlers(); if (num <= 0) return num; try { Iterator iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = (SelectionKey) iterator.next(); iterator.remove(); IHandleEvent handlers = (IHandleEvent) key.attachment(); int r1 = 0; if (! key.isValid()) continue; else if (key.isAcceptable()) // for server { r1 = handlers.handleAccept(); } else if (key.isConnectable()) // 处理前一定要禁止任何操作 { key.interestOps(key.interestOps() & ~key.readyOps()); r1 = handlers.handleConnect(); } else if (key.isReadable()) { do { r1 = handlers.handleInput(); } while (r1 > 0); } else if (key.isWritable()) { if (pool != null ) { TcpWorker worker = null; if (((TCPLink)handlers).isBusy) continue; else if ((worker = pool.getIdleWorker()) == null) { try { Thread.sleep(1000); } catch (InterruptedException e) { Debug.msg(Debug.ERROR,e.getMessage()); Thread.interrupted(); } _pendingQueue.put(new PendingObj(handlers,SelectionKey.OP_WRITE,ADD_TYPE )); } else worker.setHandler(handlers); continue ; } int count = 0; do { r1 = handlers.handleOutput(); count++; if (count > 3) break; } while (r1 > 0); //连续写,r1为0时发送队列数据为空;here将来可考虑多线程 } if (r1 < 0) { unregister(handlers,true); } } } catch (Exception e) { Debug.msg(Debug.ERROR,"SelectionKey occur runtime exception:",e); return -1; } return num; }
@H_404_7@
这些都是公司大牛写的,真的博大精深,感觉自己要学的东西太多啦。@H_404_7@