2014-10-10 52 views
0

我很难理解在创建我的GameServer时Netty如何工作。现在,我只想在GameRoom中将2个Netty频道分组。下面显示了我的思考过程的代码,但是我也会在这里解释它。如何在制作游戏服务器时考虑Netty?

当有人连接时,我想与其他玩家配对。如果没有人可用,我希望他们等到有人可以玩。一旦有人可以与之一起玩,我想将它们都粘在我的游戏实例中,使用它们的通道发送输入并从服务器接收数据。

为了得到一些有用的东西,我想我只需要在游戏类中模拟服务器端的随机输入,当它计算出谁是赢家时,就会将它发送到特定游戏室中的两个通道(这就是试图在下面的代码中建模的东西)。

当我在创建游戏时写入Channel对象时,它们可用并且可以工作。当我尝试从写入方法访问它们时,它们不可用,并显示为空指针异常。

我真的不知道如何使用netty来发挥它的潜力,如果有任何关于改善这一点的建议,请让我知道。另外,我知道有一个基于Netty构建的Java游戏服务器,但我宁愿自己使用Netty来实现我自己的服务器作为学习体验。

感谢所有

public class GameRoom extends Game { 
    private OnlinePlayer p1; 
    private OnlinePlayer p2; 

    public GameRoom(Channel p1, Channel p2) { 
     this.p1 = new OnlinePlayer("Tucker", p1); 
     this.p2 = new OnlinePlayer("Bad Kid", p2); 
     p1.writeAndFlush("Game Starting\n"); 
     p2.writeAndFlush("Game Starting\n"); 
     startGame(); 
    } 

    public void write(String msg) { 
     System.out.println(msg); 

     p1.getChannel().writeAndFlush(msg + "\n"); 
     p2.getChannel().writeAndFlush(msg + "\n"); 
    } 

    @Override 
    public void gameOver() { 
     String msg = String.format("Winner is %s, with score of %d!", getManager().getWinner().getName(), getManager().getWinner().getScore()); 
     write(msg); 
    } 

} 

public class GameServerHandler extends SimpleChannelInboundHandler<String> { 
    static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); 
    static final HashMap<SocketAddress, GameRoom> gameRoomMap = new HashMap<SocketAddress, GameRoom>(); 
    static final LinkedList<Channel> queue = new LinkedList<Channel>(); 

    @Override 
    protected void messageReceived(ChannelHandlerContext ctx, String msg) 
      throws Exception { 
     // TODO Auto-generated method stub 
     for (Channel c: channels) { 
      if (c != ctx.channel()) { 
       System.out.println("Writing to other channels!"); 
       c.writeAndFlush("[" + ctx.channel().remoteAddress() + "] " + msg + '\n'); 
      } else { 
       c.writeAndFlush("[you] " + msg + '\n'); 
      } 
     } 
    } 

    @Override 
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception { 
     super.handlerAdded(ctx); 
     Channel c = ctx.channel(); 
     channels.add(c); 
     if (!queue.isEmpty()) { 
      Channel pair = queue.pop(); 
      GameRoom g = new GameRoom(c, pair); 
     } 
     else { 
      queue.add(c); 
     } 
     System.out.println(channels); 
    } 

    @Override 
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { 
     super.handlerRemoved(ctx); 
     System.out.println("Removing"); 
     Channel c = ctx.channel(); 
     channels.remove(c); 
    } 
} 
+0

我想你会得到更好的回应http://codereview.stackexchange.com – StackFlowed 2014-10-10 20:01:19

+0

不知道存在。感谢您的回复,我也会在那里尝试。 – MrDiddly 2014-10-10 20:30:50

回答

0

你应该写到通道背景下网状IO线程,当请求到达ChunkedStream你的线程安全的实现。你也应该通过游戏线程中的这个对象提供服务器更新。

请参阅stream's package文档。尤其是ChunkedWriteHandler和ChunkedStream。

+0

原来,我不得不将GameRoom类放在它自己的线程中......然后它解决了我的问题。但我也会研究ChunkedStream的东西!我相信这将在未来为我解决问题!感谢您的回应! – MrDiddly 2014-10-11 16:18:07

+0

是的,GameRoom应该在单独的线程中。另外你应该记住,该通道不能直接在处理程序外使用。您可以自由地使用您的响应对象来操作 - 这为您提供了下游连接。对于上游链接,您可以在初始请求时将播放器ID附加到频道,并使用此ID映射来自此频道的更多消息。 – ursa 2014-10-11 20:21:51

+0

因此,使用ChunkedWriteHandler发送正确的数据。我将如何去附加playerID到频道?创建一个HashMap? – MrDiddly 2014-10-11 20:49:03