我目前在与 Mina 合作时遇到问题。我能够创建 NIOAcceptor 和 Connector 并将客户端连接到服务器。在服务器中创建会话后,它会发送握手数据包,该数据包依次验证并将验证发送回服务器以查看文件是否是最新的等。服务器接收此验证并正确解密数据包并发送数据包到客户端以显示游戏窗口。但是,在这个初始连接之后,我不能再通过客户端向服务器发送数据包。
服务器处理程序:
@Override
public void sessionOpened(IoSession session) {
log.info("[Login] to [" + GameConstants.GAME_NAME + ": IoSession with {} opened", session.getRemoteAddress());
Client c = new Client(session);
connectedClients.add(session.getRemoteAddress().toString());
session.setAttribute(Client.KEY, c);
c.write(PacketCreator.getHandshake());
// c.write(PacketCreator.getPing());
}
@Override
public void messageReceived(IoSession session, Object message) {
PacketReader reader = new PacketReader((byte[]) message);
Client c = (Client) session.getAttribute(Client.KEY);
short header = reader.readShort();
PacketHandler handler = PacketProcessor.getHandler(header);
System.out.println("Received opcode: 0x" + Integer.toHexString(header).toUpperCase());
if (handler != null) {
handler.handlePacket(reader, c);
} else {
log.info("Received opcode: 0x" + Integer.toHexString(header).toUpperCase() + " with no handler.");
}
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) {
System.out.println("session error");
}
@Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("Session closing: " + session.getRemoteAddress().toString());
connectedClients.remove(session.getRemoteAddress().toString());
Client c = (Client) session.getAttribute(Client.KEY);
if (c != null) {
c.disconnect();
c.dispose();
} else {
log.warn("Client is null in sessionClosed for ip {} when it shouldn't be", session.getRemoteAddress());
}
super.sessionClosed(session);
}
客户端处理程序:
@Override
public void sessionOpened(IoSession session) {
System.out.println("Session opened: " + session);
Server s = new Server(session);
session.setAttribute(Server.KEY, s);
s.write(PacketCreator.getPong());
}
@Override
public void messageReceived(IoSession session, Object message) {
PacketReader reader = new PacketReader((byte[]) message);
Server s = (Server) session.getAttribute(Server.KEY);
short header = reader.readShort();
PacketHandler handler = PacketProcessor.getHandler(header);
if (handler != null) {
handler.handlePacket(reader, s);
} else {
log.info("Received opcode: 0x" + Integer.toHexString(header).toUpperCase() + " with no handler.");
}
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) {
System.out.println("session error");
log.error("Exception caught in Server Handler: ", cause);
}
@Override
public void sessionClosed(IoSession session) throws Exception {
// TODO
System.out.println("session closed");
super.sessionClosed(session);
}
客户端(NIOConnection 类):
public static void connectToServer() throws Throwable {
NioSocketConnector connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(1000 * 30); // 30 seconds
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
connector.setHandler(new ClientHandler());
IoSession session;
long startTime = System.currentTimeMillis();
for (;;) {
try {
ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", 9494)); // 24.7.142.74
future.awaitUninterruptibly();
session = future.getSession();
break;
} catch (RuntimeIoException e) {
log.error("Failed to connect", e);
Thread.sleep(5000);
}
}
session.getCloseFuture().awaitUninterruptibly();
}
服务器(NIOAcceptor 类):
private static void initializeLoginServer() {
PacketProcessor.registerHandlers();
acceptor = new NioSocketAcceptor();
// acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));// TODO: encoding/decoding packets
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
acceptor.getSessionConfig().setTcpNoDelay(true);
acceptor.setHandler(new ServerHandler(1));
try {
acceptor.bind(new InetSocketAddress(GameConstants.SERVER_PORT));
} catch (Exception e) {
log.error("Could not bind. ", e);
}
log.info("Login Server: Listening on port " + GameConstants.SERVER_PORT);
}