当前位置: 首页 > 知识库问答 >
问题:

如何忽略来自断开信道的消息

欧阳绪
2023-03-14

我正在为多人游戏实现简单的网络服务器。我只是想搞清楚Netty

我通过telnet测试服务器。我所做的是向所有频道广播信息。工作很顺利。此外,我从地图上删除通道关闭事件,这是罚款。

但问题是,如果其中一个客户端意外断开连接,则在关闭回调之前,MessageRec的回调调用其发送方断开连接的信道。

如何正确忽略来自断开连接的客户端的消息?我在messagedReceived中使用StringBuffer,但用于StringBuffer的情况。toString也不是正确的字符串。在断开连接的通道结束时,将无意义的消息广播到其他通道和自身,当接收器通道本身处于关闭状态时,会引发异常由对等方重置连接,这是正常的,因为此时通道本身不可用。

这是代码;

     @Override
     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {

            System.out.println();
            System.out.println("------------------");


            Channel current = e.getChannel();
            System.out.println("SenderChannel:"+current.getId());

            if(!current.isOpen())
                System.out.println("Not Open");

            ChannelBuffer buf = (ChannelBuffer) e.getMessage();

            StringBuffer sbs = new StringBuffer();

            while(buf.readable()) {
                sbs.append((char) buf.readByte());
            }

            String s = sbs.toString();


            System.out.println(s);

            String you = "You:" + s;
            String other = "Other:" + s;



            byte [] uResponse = you.getBytes();
            byte [] otherResponse = other.getBytes();


            Iterator iterator = channelList.entrySet().iterator();
            while(iterator.hasNext()){
                  Map.Entry pairs = (Map.Entry)iterator.next();

                  Integer key = (Integer)pairs.getKey();
                  Channel c = (Channel)pairs.getValue();

                  System.out.println("ReceiverChannel:"+c.getId());

                  if(key != current.getId())
                      c.write(ChannelBuffers.wrappedBuffer(otherResponse));
                  else
                      c.write(ChannelBuffers.wrappedBuffer(uResponse));

            }

     }


    @Override
    public void channelDisconnected(ChannelHandlerContext ctx,
            ChannelStateEvent e){

        Channel ch = e.getChannel();


            channelList.remove(ch.getId());
            System.out.println();
            System.out.println("*****************");
            System.out.println("DisconnectEvent:"+ch.getId());
            System.out.println("*****************");
            System.out.println();
            ch.close();

    }

共有3个答案

黄飞翮
2023-03-14

如果这是一个多人游戏服务器,它可能更好地使用现有的Netty游戏服务器解决方案,如java游戏服务器。断开连接成为发送到会话的事件,由于它是事件驱动的,您可以编写自己的处理程序来决定是否在同一会话上接收更多的事件。由于事件按照先进先出的顺序排队,如果发生断开连接,则不需要继续进行后续广播。

连正信
2023-03-14

只需在每次发送周围放一个尝试/捕捉。如果其中一个失败,关闭相应的通道。

诸葛立果
2023-03-14

你不能以你想要的方式解决这个问题。例如,如果有网络问题,那么从技术上讲,发送者可以随时断开连接

  • 一旦线程输入messageReceived
  • 当您在频道列表中迭代时
  • 当您在频道列表中迭代时,但在您回显给发件人后
  • 在你广播完信息之后

Netty不能引发断开连接的事件,因为你正在运行的线程将引发事件(除非你有一个无序的执行处理程序在你的管道)。正确的解决方案取决于您的应用程序。如果广播导致所有其他接收器响应,那么让服务器禁止发送给不再连接的客户端的任何消息可能会更好/更容易。

此外,如果您真的要使用字符串,请看一下StringEncoder/StringDecoder。代码中不能保证消息事件缓冲区包含完整的html" target="_blank">字符串。

 类似资料:
  • 这个想法是:我有N个WCF服务,它们连接并订阅了同一个Redis消息通道。这些服务使用此通道交换消息,以同步一些缓存和其他数据。 每个服务如何可以忽略自己的消息?即,如何向除我以外的所有人发布?

  • 试图从其他人那里得到答案 假设我有一个简单的控制器,如下所示: 我希望处理忽略“取消”信号,这通常在客户端断开连接时出现。试图通过nginx的

  • Im使用django通道来实现我的项目中的即时消息应用程序。消息框不占用整个屏幕,所以我尝试使用ajax实现它。Im面临的问题是ajax中的url字段是以http://locahost为前缀的。我不想这样做,因为Im使用ASGI和django通道来实现ws:// 我尝试在url前面加上“/” 我希望url为ws://localhost:8000/messages/ 我现在得到的是 http://l

  • #include <stdio.h> int main(void) { int i = 0; int sum = 0; for (i = 1; i <= 200; i++) { sum += i; } printf("%d\n", sum); return

  • 结果 狙击在X频道发送的消息,而不是不和谐公会内的所有频道。也就是说,它应该只跟踪该通道中的消息删除(由其ID标识),并且只响应命令。我这里的当前代码狙击了不和谐公会内发送的每一条消息。 问题 我如何狙击在X通道而不是整个公会发送的消息? 我主要打算在一个行会中运行这个机器人。然而,如果需要的话,它可以扩展到多个公会,那就太好了。 到目前为止,我的代码如下。

  • 如何通过忽略主题中所有现有的消息来只使用来自Kafka主题的最新消息。我有两个相同主题的使用者,当我开始使用来自该主题的消息时,它会获取最早的消息。我需要在我的使用者启动后使用消息。我在消费者配置中尝试了此配置,但这不起作用。