如何找出Netty 5 UDP中导致异常的地址?

时间:2016-06-15 19:25:01

标签: java sockets udp netty

简介

我是JRakNet的创建者,这是一个网络库,它实现了Java的最新协议RakNet的基础知识。我创建了这个库,所以我可以为Minecraft制作一个多人游戏服务器:使用RakNet的Pocket Edition。

问题

然而,我在服务器和客户端遇到的一个问题是处理程序的异常处理。无论何时发送无效数据包,都会错误地读取数据,并且会像正常情况一样抛出异常。但是,我需要找到一种方法来找出导致异常的外部地址。

为什么我无法解决问题

通常,在使用ServerBootstrap的TCP服务器上,我能够对boss和worker组进行分组,因此当捕获到异常时,我知道它来自哪里,因为客户端拥有专用于它的自己的处理程序。但RakNet是UDP,这意味着它是无连接的,数据包可以来自任何地方,所以我只有一个处理程序。因此,每当抛出异常时,我都不知道是谁造成了它。我尝试过忽略异常列表,但我认为效率低下。我已经尝试在代码中使用一个名为lastSender的变量,因此无论何时抛出异常,它都会查找导致错误的原因。这是一个很好的方法来找出是谁造成了例外?或者是否有另一种更好的方法来确定谁在UDP Netty服务器上导致错误?

发布时的源文件

The RakNetClient class at the time of posting

The RakNetClientHandler classa at the time of posting

Here is the whole project code at the time of posting if needed

TL; DR

我需要找到一种好方法来确定哪个地址在原始Bootstrap Netty UDP服务器/客户端上导致异常。我曾尝试使用带有UDP的ServerBootstrap,但它似乎仍然只使用一个声明here

的频道

1 个答案:

答案 0 :(得分:1)

Netty有一个很好的线程模型since 4.0

特别是

  除非使用@Sharable注释ChannelHandler,否则Netty永远不会同时调用ChannelHandler的方法

有轻微change in 5.0

  

从开发人员的角度来看,唯一改变的是,不再保证ChannelHandler将始终由同一个线程执行。但是,保证它永远不会被两个或多个线程同时执行。此外,Netty还将处理可能发生的任何内存可见性问题。因此,无需担心ChannelHandler中的线程安全性和易失性变量。

你可以利用这个优势,只用

来解决问题
static class UdpHandler extends SimpleChannelInboundHandler<DatagramPacket> {
    private InetSocketAddress lastSender;

    @Override
    protected void messageReceived(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
        lastSender = packet.sender();
        throw new RuntimeException();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("Evil sender was: " + lastSender);
    }
}

exceptionCaught之后直接调用messageReceived方法

public static void invokeChannelReadNow(final ChannelHandlerContext ctx, final Object msg) {
    try {
        ((AbstractChannelHandlerContext) ctx).invokedThisChannelRead = true;
        ctx.handler().channelRead(ctx, msg); // -> calls messageReceived
    } catch (Throwable t) {
        notifyHandlerException(ctx, t);      // -> calls exceptionCaught
    }
}

(source)

本地变量的值仍将包含您在messageReceived中设置的内容。

相关问题