2017-05-22 7 views
0

메시지로 NioDatagramChannel 및 protoBuf를 사용하여 netty를 사용하여 UDP 서버를 작성하려고합니다.Netty + NioDatagram (UDP) + ProtoBuf 문제 - 버려진 인바운드 메시지 DatagramPacket

EventLoopGroup group = new NioEventLoopGroup(); 
try { 
    Bootstrap b = new Bootstrap(); 
    b.group(group) 
     .channel(NioDatagramChannel.class) 
     .option(ChannelOption.SO_BROADCAST, true) 
     .handler(new UdpProtoBufServerChannelInitializer()); 

    b.bind(port).sync().channel().closeFuture().await(); 
} finally { 
    group.shutdownGracefully(); 
} 

UdpProtoBufServerChannelInitializer :

public class UdpProtoBufServerChannelInitializer extends ChannelInitializer<NioDatagramChannel> { 

    static final Logger logger = Logger.getLogger(UdpProtoBufServerChannelInitializer.class); 
    @Override 
     protected void initChannel(NioDatagramChannel ch) throws Exception { 
     ChannelPipeline p = ch.pipeline(); 
     p.addFirst(new ProtobufVarint32FrameDecoder()); 
     p.addFirst(new ProtobufDecoder(Message.getDefaultInstance())); 
     p.addFirst(new ProtobufVarint32LengthFieldPrepender()); 
     p.addFirst(new ProtobufEncoder()); 

     p.addFirst(new UdpProtoBufServerHandler()); 
    } 
    } 

는 그러나, 나는 UdpProtoBufServerChannelInitializer를 실행하기 전에 자바 클라이언트로부터 메시지를받은 후 다음과 같은 오류를보고하고 여기에 서버 구현입니다.

디버그 DefaultChannelPipeline : 76 - 폐기 DatagramPacket의 인바운드 메시지 (/127.0.0.1:60556 => 0.0.0.0/0.0.0.0:55559, PooledUnsafeHeapByteBuf (ridx 2048) 0 widx : 34 CAP)에 도달 파이프 라인의 꼬리. 파이프 라인 구성을 확인하십시오.

또한, 확실하지 않은 응용 프로그램을 실행하는 것은 관련이 예외 경우 : 파이프 라인이 더 소비자가 없습니다처럼

2017-05-22 14:31:09 DEBUG PlatformDependent0:91 - jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable 
java.lang.ClassNotFoundException: jdk.internal.misc.Unsafe 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
    at io.netty.util.internal.PlatformDependent0$6.run(PlatformDependent0.java:295) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at io.netty.util.internal.PlatformDependent0.<clinit>(PlatformDependent0.java:288) 
    at io.netty.util.internal.PlatformDependent.getSystemClassLoader(PlatformDependent.java:895) 
    at io.netty.util.internal.PlatformDependent.isAndroid0(PlatformDependent.java:919) 
    at io.netty.util.internal.PlatformDependent.<clinit>(PlatformDependent.java:70) 
    at io.netty.util.ConstantPool.<init>(ConstantPool.java:32) 
    at io.netty.util.Signal$1.<init>(Signal.java:27) 
    at io.netty.util.Signal.<clinit>(Signal.java:27) 
    at io.netty.util.concurrent.DefaultPromise.<clinit>(DefaultPromise.java:43) 
    at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:36) 
    at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:58) 
    at io.netty.channel.MultithreadEventLoopGroup.<init>(MultithreadEventLoopGroup.java:52) 
    at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:87) 
    at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:82) 
    at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:63) 
    at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:51) 
    at io.netty.channel.nio.NioEventLoopGroup.<init>(NioEventLoopGroup.java:43) 

답변

0

감사합니다. 나는 마지막으로,이 작업을 수행하는 방법을 알아 냈 :

public class DatagramServerHandler extends SimpleChannelInboundHandler<DatagramPacket> { 

    @Override 
    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception { 
     Message message = SocketProtos.Message.parseFrom(packet.content().nioBuffer()); 
     ctx.writeAndFlush(packet.retain()); 
    } 

    @Override 
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 
     cause.printStackTrace(); 
     ctx.close(); 
    } 
} 

는 그냥 NioDatagram UDP 표준 구현을 사용하고 ProtoBuf 메시지 바이트 []에 메시지를 구문 분석합니다.

0

글쎄, 그것은 보인다. 데이터를 처리하는 사용자 정의 처리기를 배치해야합니다. p.addFirst(new ProtobufVarint32FrameDecoder()); 전에 p.addFirst(new MyHandler()); 또는 p.addFirst(new UdpProtoBufServerHandler());p.addLast(new MyHandler()); 뒤에 할 수 있습니다.

실제로 코드에서 addFirst 대신 addLast을 사용한다고 가정 할 수 있습니다. addLast을 사용하는 경우 파이프 라인 ProtobufVarint32FrameDecoder -> ProtobufDecoder -> ... -> UdpProtoBufServerHandler에 신고하면 주문을 받게됩니다. 귀하의 경우 (addFirst) UdpProtoBufServerHandler -> ProtobufEncoder -> ... -> ProtobufVarint32FrameDecoder은 첫 번째 위치에 처리기가 있고 끝에 디코더가 있기 때문에 잘못 보입니다.

+0

제안 해 주셔서 감사합니다. addLast로 변경 한 후에도 여전히 동일한 오류가 표시됩니다. 이것은 제 구현입니다 : 'ChannelPipeline p = ch.pipeline(); p.addLast (새 UdpProtoBufServerHandler()); p.addLast (new ProtobufVarint32FrameDecoder()); p.addLast (new ProtobufDecoder (Message.getDefaultInstance())); p.addLast (new ProtobufVarint32LengthFieldPrepender()); p.addLast (new ProtobufEncoder()); p.addLast (새 UdpProtoBufServerHandler());' – flashsnake