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
*
*/
}