package server; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import org.apache.log4j.Logger; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.future.IoFuture; import org.apache.mina.core.future.IoFutureListener; import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.springframework.context.support.ClassPathXmlApplicationContext; import exception.NoIpException; import tools.DataTypeTranslater; import tools.Debug; /** * 服务器的网络层,负责网络交互 * * @author Feng * */ public class ServerNetwork { // 轮询"等待client回复"的超时时间 public static final long WAIT_CLIENT_RESPONSE_TIMEOUT = 3000; // 轮询"等待client回复"的重发次数 public static final long WAIT_CLIENT_RESPONSE_TIMES = 3; // public static ServerNetwork instance = new ServerNetwork(); private ServerModel serverModel; private ClientRequest_Dispatcher clientRequest_Dispatcher; private MinaServerHandle minaServerHandle; private ProtocolCodecFilter protocolCodecFilter; private MyLogger myLogger; private InetAddress addr; Logger logger = Logger.getLogger(ServerNetwork.class); private InetSocketAddress inetSocketAddress; private IoAcceptor acceptor; public ServerNetwork() { } /** * 初始化 * * @throws IOException * @author Feng */ public void init() { if (addr != null || minaServerHandle == null) return; // 显示IP地址 try { addr = InetAddress.getLocalHost(); logger.info("IP address:" + addr.getHostAddress().toString()); logger.info("Host Name:" + addr.getHostName().toString()); } catch (UnknownHostException e1) { e1.printStackTrace(); } // Debug.log("Port Number:8081"); logger.debug("Port Number:8081"); acceptor = new NioSocketAcceptor(); // 指定编码解码器 acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new MinaEncoder(), new MinaDecoder())); // System.out.println("22222222222222222222222222"); if (myLogger == null) myLogger = new MyLogger(); // System.out.println(myLogger == null); acceptor.getFilterChain().addLast("Logger", myLogger); // System.out.println("codec " + (protocolCodecFilter == null)); // acceptor.getFilterChain().addLast("codec", protocolCodecFilter); acceptor.getSessionConfig().setMaxReadBufferSize(1024 * 8); // System.out.println("minaServerHandle :" + (minaServerHandle == // null)); acceptor.setHandler(minaServerHandle); // acceptor.setHandler(new MinaServerHandle()); try { acceptor.bind(new InetSocketAddress(8081)); } catch (IOException e) { e.printStackTrace(); logger.error("ServerNetwork : Acceptor bind Exception!;\n" + e.toString()); } // new ClassPathXmlApplicationContext("trapReceiverContext.xml"); } public void onDestroy() { acceptor.unbind(inetSocketAddress); } public ServerModel getServerModel() { return serverModel; } public void setServerModel(ServerModel serverModel) { this.serverModel = serverModel; } public ClientRequest_Dispatcher getClientRequest_Dispatcher() { return clientRequest_Dispatcher; } public void setClientRequest_Dispatcher(ClientRequest_Dispatcher clientRequest_Dispatcher) { this.clientRequest_Dispatcher = clientRequest_Dispatcher; } public MinaServerHandle getMinaServerHandle() { return minaServerHandle; } public void setMinaServerHandle(MinaServerHandle minaServerHandle) { this.minaServerHandle = minaServerHandle; } public ProtocolCodecFilter getProtocolCodecFilter() { return protocolCodecFilter; } public void setProtocolCodecFilter(ProtocolCodecFilter protocolCodecFilter) { this.protocolCodecFilter = protocolCodecFilter; } public MyLogger getMyLogger() { return myLogger; } public void setMyLogger(MyLogger myLogger) { this.myLogger = myLogger; } /** * 添加一个等待客户端回复的监听(服务器向客户端发送消息后,要求客户端回复) * * @param ioSession * @param key * @param messageHasSentww * @author Feng */ public void sendToClient(IoSession ioSession, PacketFromServer packetFromServer) { sendToClient(new WaitClientResponse(ioSession, packetFromServer)); } public void sendToClient(final WaitClientResponse waitClientResponse) { sendToClient(waitClientResponse, 0); } private void sendToClient(final WaitClientResponse waitClientResponse, final int times) { try { if (serverModel.getClientUserFromTable(waitClientResponse.ioSession) == null) { // 用户已掉线, 调用删除前的回调,然后删除 if (waitClientResponse.waitClientResponseCallBack != null) waitClientResponse.waitClientResponseCallBack.beforeDelete(); return; } // 用户在线,重发 WriteFuture writeFuture = waitClientResponse.ioSession.write(waitClientResponse.packetFromServer); // writeFuture.awaitUninterruptibly(WAIT_CLIENT_RESPONSE_TIMEOUT); writeFuture.addListener(new IoFutureListener<IoFuture>() { @Override public void operationComplete(IoFuture future) { if (((WriteFuture) future).isWritten()) return; else { // Debug.log("ServerModel", // "Wait for Client(" + // serverModel.getIoSessionKey(waitClientResponse.ioSession) // + ") response timeout!"); try { logger.info("ServerModel Wait for Client(" + serverModel.getIoSessionKey(waitClientResponse.ioSession) + ") response timeout!"); if (times < WAIT_CLIENT_RESPONSE_TIMES) { // 小于重发极限次数,重发 // Debug.log("ServerModel", "Client(" + // serverModel.getIoSessionKey(waitClientResponse.ioSession) // + ") online,send again!"); logger.info("ServerModel Client(" + serverModel.getIoSessionKey(waitClientResponse.ioSession) + ") online,send again!"); sendToClient(waitClientResponse, times + 1); } else { // 大于重发极限次数,抛弃 logger.info("To many times, abandon!"); return; } } catch (Exception e) { } } } }); } catch (NoIpException e) { e.printStackTrace(); if (waitClientResponse.waitClientResponseCallBack != null) waitClientResponse.waitClientResponseCallBack.beforeDelete(); return; } } /** * Mina网络连接回调方法 * * @author Feng * */ }