【问题标题】:How to find out which address caused exception in Netty 5 UDP?如何找出在 Netty 5 UDP 中导致异常的地址?
【发布时间】:2016-06-15 19:25:00
【问题描述】:

简介

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

问题

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

为什么我无法解决问题

通常,在使用 ServerBootstrap 的 TCP 服务器上,我可以将老板和工作组分组,因此当捕获到异常时,我知道它来自哪里,因为客户端有自己的专用处理程序。但是 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

所述

【问题讨论】:

  • 仅供参考:Netty 5 已死。 4.1是新的头。

标签: java sockets udp netty


【解决方案1】:

Netty 有一个不错的线程模型since 4.0

特别是

Netty 永远不会同时调用 ChannelHandler 的方法,除非 ChannelHandler 被 @Sharable 注解

有轻微的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 中设置的任何值。

【讨论】:

    猜你喜欢
    • 2018-05-30
    • 1970-01-01
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多