java - 如何找出 Netty 5 UDP 中哪个地址导致异常?

标签 java sockets udp netty

简介

我是 JRakNet 的创建者,一个实现最新协议(protocol)基础知识的网络库 RakNet对于Java。我制作了这个库,这样我就可以为 Minecraft:袖珍版制作一个使用 RakNet 的多人游戏服务器。

问题

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

为什么我无法解决问题

通常,在使用 ServerBootstrap 的 TCP 服务器上,我可以将 boss 组和工作组分组,因此当捕获异常时,我知道它来自哪里,因为客户端有自己的专用处理程序。但 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 服务器/客户端上引起了异常。我尝试将 ServerBootstrap 与 UDP 结合使用,但似乎它仍然只使用一个 channel ,如 here 所示。

最佳答案

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

尤其

Netty will never call a ChannelHandler's methods concurrently, unless the ChannelHandler is annotated with @Sharable

有轻微的change in 5.0但是

From a developer's point of view, the only thing that changes is that it's no longer guaranteed that a ChannelHandler will always be executed by the same thread. It is, however, guaranteed that it will never be executed by two or more threads at the same time. Furthermore, Netty will also take care of any memory visibility issues that might occur. So there's no need to worry about thread-safety and volatile variables within a 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 中设置的值。

关于java - 如何找出 Netty 5 UDP 中哪个地址导致异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37844115/

相关文章:

java - 当我从套接字接收到一些数据时,为什么会附加大量空格?

c - recvfrom - 接收任意大小的结构?

linux - BeagleBone Black : Qt 5. 3 无法在 UDP 中发送数据报

java - 如何在 JAVA 中使用正则表达式在字符串行中查找特定字符串?

java - JPA中是否有查询类的参数化版本?

java - 使用不同的包名称跨不同应用程序反/序列化 java 对象

linux - 内核中 udp header 的 skb_push 在哪里?

java - 尝试制作一款基于 Ascii 的游戏; JFrame不显示

python - 通过网络发送字符串

java - Android Socket + ObjectOutputStream 无法正常工作