我参与了一个IOT项目,并试图整理学习曲线和一个奇怪的角度的方法。我是一名.Net程序员,它似乎是Netty的入门库,这是基于Java的。我们的客户已经在研究如何将它放在他们的设备上,并坚持使用HTTP而不是MQTT,因为他们不希望防火墙配置成为正常因素。
所以,我要告诉您的第一件事是,我第一次尝试使用DotNetty作为客户端和代理,但是我无法理解库的正面或反面,因为它没有文档,我无法将我在对象资源管理器中看到的对象与我在Netty文档中看到的对象联系起来。然后我突然想到,也许我可以像我在Xamarin中看到的那样,从C#代码中明显地访问Java库。这就导致了LKVM,它允许我将Netty文件转换为一个DLL文件。
因此,当我使用Visual和C#时,我现在能够遵循Netty教程和文档,这允许了相当多的进步。
我写了一个小小的控制台应用程序,它应该像一个带有Netty客户端的IOT设备。我使用我生成的DLL来编写一个客户端。我试图连接时出了一个错误,并假设由于没有代理,所以它只是找不到端点。所以今天我写了服务器代码。一旦我完成,我试图再次连接设备,并得到了同样的错误。
然后我点燃了Fiddler,这样我就可以检查交通情况,发现没有车了。因此,此错误是在进行任何连接尝试之前发生的。
因此,在我进一步讨论之前,下面是客户端代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JSON = Newtonsoft.Json.JsonConvert;
using io.netty.util;
using io.netty.bootstrap;
using io.netty.buffer;
using io.netty.channel;
using io.netty.channel.nio;
using io.netty.channel.socket;
using io.netty.channel.socket.nio;
using io.netty.handler.codec.http;
using io.netty.handler.codec.http.websocketx;
using io.netty.handler.codec.http.websocketx.extensions.compression;
using io.netty.handler.ssl;
using io.netty.handler.ssl.util;
using java.io;
using java.net;
using io.netty.util.concurrent;
namespace Device
{
public class WebSocketClient
{
public string URL { get; set; }
public URI Uri = null;
public Uri netUri = null;
public string Host;
public int Port;
public Channel Channel;
public Bootstrap BootStrap = new Bootstrap();
public WebSocketClientHandler Handler;
public EventLoopGroup Group = new NioEventLoopGroup();
public SslContext SslCtx = null;
public WebSocketClient(string URL)
{
this.URL = URL;
netUri = new Uri(this.URL);
Uri = new URI(URL);
Host = netUri.Host;
Port = netUri.Port;//Unlike the Netty example, .Net knows the ws/wss ports.
bool SSL = Port == 443;
if (SSL)
{
SslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
}
Handler = new WebSocketClientHandler(WebSocketClientHandshakerFactory.newHandshaker(Uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders()));
//BootStrap.group(Group).channel(new NioSocketChannel().GetType().handler(new ChannelInitializer(Handler, Host, Port, SslCtx))).connect(Host, Port).sync().channel();
}
public void Connect()
{
//Channel = BootStrap.connect(Host, Port).sync().channel();
//Channel = BootStrap.connect().sync().channel();
//((Bootstrap)BootStrap.group(Group).channel(new NioSocketChannel().GetType()).handler(new ChannelInitializer(Handler, Host, Port, SslCtx))).connect(Host, Port).sync().channel();
BootStrap = BootStrap.group(Group) as Bootstrap;
BootStrap = BootStrap.channel(new NioSocketChannel().GetType()) as Bootstrap;
BootStrap = BootStrap.handler(new ChannelInitializer(Handler, Host, Port, SslCtx)) as Bootstrap;
//BootStrap.remoteAddress(Host, Port);
//BootStrap.localAddress(Host, Port);
ChannelFuture cf = BootStrap.connect(Host, Port);
cf = cf.sync();
Channel = cf.channel();
Handler.HandshakeFuture().sync();
}
public void Close()
{
Group.shutdownGracefully();
}
public void Ping()
{
WebSocketFrame frame = new PingWebSocketFrame(Unpooled.wrappedBuffer(new byte[] { 8, 1, 8, 1 }));
Channel.writeAndFlush(frame);
}
public void Send(string content)
{
Channel.writeAndFlush(content);
Channel.newPromise().addListener(new Listener());
}
}
public class Listener : GenericFutureListener
{
public void operationComplete(Future f)
{
System.Console.WriteLine(JSON.SerializeObject(f.get()));
}
}
}在构造函数中,有一个注释行,它模仿客户端示例中的内容。因为它是链子的,所以很难分辨错误是从哪里来的。所以,我把它移到我的连接函数中,并将其分解。
在connect函数中,在下面的线路上,我看到了故障的第一个迹象:
ChannelFuture cf = BootStrap.connect(Host, Port);如果我看一下我的“手表”中的对象,我可以看到似乎已经出现了一个错误。看起来是这样的:
{DefaultChannelPromise@67755d(failure: java.lang.ExceptionInInitializerError)}但是,它没有在该行上出错,而是在以下行上出错:
cf = cf.sync();堆栈跟踪如下所示:
at io.netty.util.internal.PlatformDependent0.throwException(Exception )
at io.netty.util.internal.PlatformDependent.throwException(Exception t)
at io.netty.util.concurrent.DefaultPromise.rethrowIfFailed()
at io.netty.util.concurrent.DefaultPromise.sync()
at io.netty.channel.DefaultChannelPromise.sync()
at io.netty.channel.DefaultChannelPromise.<bridge>sync()
at io.netty.channel.DefaultChannelPromise.io.netty.channel.ChannelFuture/()Lio.netty.channel.ChannelFuture;sync()
at Device.WebSocketClient.Connect() in c:\Users\ME\Documents\Visual Studio 2017\Projects\MQTT Sandbox\Device\WebSocketClient.cs:line 70
at Device.Program.SocketTest() in c:\Users\ME\Documents\Visual Studio 2017\Projects\MQTT Sandbox\Device\Program.cs:line 106
at Device.Program.Main(String[] args) in c:\Users\ME\Documents\Visual Studio 2017\Projects\MQTT Sandbox\Device\Program.cs:line 72我唯一的另一条线索是,如果我探索这个异常,就会发现异常有一个子异常(与内部异常相反),即:“未知指针大小”。堆栈跟踪如下所示:

今天,我花了很大一部分时间进行修补和研究,我完全没有找到什么不对劲的线索。任何帮助都将不胜感激。
提前感谢您的帮助!
Update I能够从ChannelFuture cf =BootStrap.connect(主机,端口)中提取更好的堆栈跟踪;
May 29, 2018 8:25:37 AM io.netty.channel.DefaultChannelId defaultProcessId
WARNING: Failed to find the current process ID from ''; using a random value: -251539282
May 29, 2018 8:25:43 AM io.netty.channel.AbstractChannel$AbstractUnsafe register
WARNING: Force-closing a channel whose registration task was not accepted by an event loop: [id: 0x6312b48a]
java.lang.ExceptionInInitializerError
at io.netty.util.internal.shaded.org.jctools.queues.LinkedArrayQueueUtil.modifiedCalcElementOffset(LinkedArrayQueueUtil.java:24)
at io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueue.offer(BaseMpscLinkedArrayQueue.java:308)
at io.netty.util.concurrent.SingleThreadEventExecutor.offerTask(SingleThreadEventExecutor.java:330)
at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:321)
at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:765)
at io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:479)
at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:81)
at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:74)
at io.netty.channel.MultithreadEventLoopGroup.register(MultithreadEventLoopGroup.java:86)
at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:333)
at io.netty.bootstrap.Bootstrap.doResolveAndConnect(Bootstrap.java:163)
at io.netty.bootstrap.Bootstrap.connect(Bootstrap.java:145)
at io.netty.bootstrap.Bootstrap.connect(Bootstrap.java:126)
at cli.Device.WebSocketClient.Connect(WebSocketClient.cs:70)
at cli.Device.Program.SocketTest(Program.cs:106)
at cli.Device.Program.Main(Program.cs:72)
Caused by: java.lang.IllegalStateException: Unknown pointer size
at io.netty.util.internal.shaded.org.jctools.util.UnsafeRefArrayAccess.<clinit>(UnsafeRefArrayAccess.java:51)
... 11 more
May 29, 2018 8:25:43 AM io.netty.util.concurrent.DefaultPromise safeExecute
SEVERE: Failed to submit a listener notification task. Event loop shut down?
java.lang.NoClassDefFoundError: Could not initialize class io.netty.util.internal.shaded.org.jctools.util.UnsafeRefArrayAccess
at io.netty.util.internal.shaded.org.jctools.queues.LinkedArrayQueueUtil.modifiedCalcElementOffset(LinkedArrayQueueUtil.java:24)
at io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueue.offer(BaseMpscLinkedArrayQueue.java:308)
at io.netty.util.concurrent.SingleThreadEventExecutor.offerTask(SingleThreadEventExecutor.java:330)
at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:321)
at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:765)
at io.netty.util.concurrent.DefaultPromise.safeExecute(DefaultPromise.java:764)
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:438)
at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:104)
at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84)
at io.netty.channel.AbstractChannel$CloseFuture.setClosed(AbstractChannel.java:1148)
at io.netty.channel.AbstractChannel$AbstractUnsafe.register(AbstractChannel.java:491)
at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:81)
at io.netty.channel.SingleThreadEventLoop.register(SingleThreadEventLoop.java:74)
at io.netty.channel.MultithreadEventLoopGroup.register(MultithreadEventLoopGroup.java:86)
at io.netty.bootstrap.AbstractBootstrap.initAndRegister(AbstractBootstrap.java:333)
at io.netty.bootstrap.Bootstrap.doResolveAndConnect(Bootstrap.java:163)
at io.netty.bootstrap.Bootstrap.connect(Bootstrap.java:145)
at io.netty.bootstrap.Bootstrap.connect(Bootstrap.java:126)
at cli.Device.WebSocketClient.Connect(WebSocketClient.cs:70)
at cli.Device.Program.SocketTest(Program.cs:106)
at cli.Device.Program.Main(Program.cs:72)发布于 2019-03-07 23:49:19
我找到了一个解决方案,并在我的IKVM分支中实现了一个修复程序。https://github.com/Draspax/ikvm8
基本上,在类io.netty.util.internal.shaded.org.jctools.util.UnsafeRefArrayAccess中有一个对UnsafeAccess.UNSAFE.arrayIndexScale(Object[].class);的调用,它应该返回4或8,而IKVM不安全的实现不考虑Object[].class,所以它返回默认的1。
希望当这些家伙让IKVM存活下来的时候,就能被包括在https://github.com/wwrd/ikvm8中。
https://stackoverflow.com/questions/50518771
复制相似问题