今天实在百无聊赖的看着代码,实在是没有意思,项目还要等到下个月启动,突然发现项目中的设计模式
挺有趣的,就翻出来看看。
因为我们项目中的结构是客户端-服务端,cs结构的,然后他们之间的通信,是怎么回事情的呢?
以前粗略的看了,主要是通过tcp\ip方式进行通信,但是至少概念中知道吧。今天就翻看一下server代码。
先来了解一下什么是reactor设计模式,反应堆模式。
Reactor设计模式中的要素如下:
Handles,也就是网络连接,文件句柄等。是事件源。
Synchronous Event Demultiplexer,同步事件的解复用(或者说派发),具体的比如select调用。比select更加高效的有linux下的epoll,freebsd下的kqueue以及windows下的iocp(IO Completion port)。
Initiation Dispatcher,注册、移除和分派事件处理句柄。
Event Handler,就是事件处理句柄。
结合上面的描述,给出来自参考资料[3]图片如下:
下面这个是项目中的类图:
1.reactor 负责响应IO事件,一旦发生,广播到响应的TcpThreadPool,TcpThreadPool发送给响应的IHandleEvent实现类去处理。
2. handler是非阻塞行为,同时负责将handlers与event事件绑定。
这里是refactor的handEvent方法;
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, this, e);
}
break;
default:
try
{
updateSelectCol(handler);
}
catch (Exception e)
{
Debug.msg(Debug.ERROR, "updateSelectCol occur exception:", e.getMessage());
Debug.logOut(Debug.ERROR, this, 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, this, 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, this , 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.getMessage());
Debug.logOut(Debug.ERROR, this, e);
return -1;
}
return num;
}
这些都是公司大牛写的,真的博大精深,感觉自己要学的东西太多啦。