Java中的应用程序协议实现

时间:2015-01-19 14:18:03

标签: java protocols

我想在Java中实现现有协议(仅限服务器端)。客户端是一个旧游戏客户端,我想为其编写服务器。

协议的结构如下:

+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+----//----+--------+--------+
| size0  | size1  |  seq0  |  seq1  | sessID0| sessID1| param0 | param1 |   id0  |   id1  |  payload | trash  | trash  |
+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+----//----+--------+--------+

现在这个协议很老了,它定义了许多版本,其中标题(直到包含id1)保持不变(与最后两个填充字节一样)。

payload因版本而异,因此需要对其进行不同的解码。请参阅下面的简化示例(pl#了解有效负载字节数):

Version 1.00    
    ...+--------+--------+--------+--------+--------+--------/--------+--------+...
(HEAD) |  pl0   |  pl1   |  pl2   |  pl3   |  pl4   |  pl5  ...  pl22 |  pl23  |
    ...+--------+--------+--------+--------+--------+--------/--------+--------+...
       | clientVersion (little endian)     | userName (fixed String l=20)      |
    ...+--------+--------+--------+--------+--------+--------/--------+--------+


Version 1.10
    ...+--------+--------+--------+--------+--------+--------/--------+--------+...
(HEAD) |  pl0   |  pl1   |  pl2   |  pl3   |  pl4   |  pl5  ... plN-1 |  plN   |
    ...+--------+--------+--------+--------+--------+--------/--------+--------+...
       | clientVersion (big endian)        | userName (pascal String)          |
    ...+--------+--------+--------+--------+--------+--------/--------+--------+

现在我的问题是双重的。

首先,如何在不进入switch()地狱的情况下实施这样的协议?我已经读过很多人推荐FSM(或者可能是状态模式),但我没有得到它应该如何工作。我一直在研究(和玩)Google的ProtoBuf,遗憾的是它不支持任何int16 / uint16数据类型。

其次,如何实现这一点,以便最终得到一个漂亮,干净的PacketHandler接口,可能如下所示:

public interface PacketHandler {

    void onLoginRequest(Client client, LoginRequest request);
    void onHeartbeatRequest(Client client, HeartbeatRequest request);
    ...

}

该处理程序的目的是,无论客户端版本如何,类LoginRequestHeartbeatRequest都是相同的。

在我希望能够编写这些POJO的事情的外向方面,例如:

public class PacketHandlerImpl implements PacketHandler {

    void onLoginRequest(Client client, LoginRequest request) {
        if(success)
            client.send(new LoginGrantedResponse(...));
        else
            client.send(new LoginDeniedResponse(...));
    }
    ...

}

提前感谢您的帮助!

0 个答案:

没有答案