当前位置: 首页 > 知识库问答 >
问题:

如何在Java中使用Netty中的channelhandler处理String和HttpRequest?

费辰阳
2023-03-14

我想处理两个不同的客户。一种是发送字符串数据包的简单tcp客户端。另一个是http客户端,它发送httprequest消息。我是Netty的初学者,我不知道管道中的处理程序是如何流动的。

这是我的服务器编码:

public class TCPServer {

    int port;

    public static void main(String[] args) {
        new TCPServer().start();
    }

    public void start() {
        port = 1222;
        EventLoopGroup producer = new NioEventLoopGroup();
        EventLoopGroup consumer = new NioEventLoopGroup();

        try {

            ServerBootstrap bootstrap = new ServerBootstrap()
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .group(producer, consumer)//separate event loop groups to handle for parent and child for handling all chanel events
                    .channel(NioServerSocketChannel.class)//select type of chanel
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ServerAdapterInitializer());//configure chanel pipeline
            System.out.println("Server started");// configuring server channel
            bootstrap.bind(port).sync().channel().closeFuture().sync();//start the server and Wait until the server socket is closed. Thread gets blocked. 

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            producer.shutdownGracefully();
            consumer.shutdownGracefully();
        }

    }

}

这是我的服务器初始值设定项:

<pre>public class ServerAdapterInitializer extends ChannelInitializer<SocketChannel> {//special chanel handler configures registered chanel pipeline

    @Override
    protected void initChannel(SocketChannel channel) throws Exception {//this method is called once the chanel was registered
        ChannelPipeline pipeline = channel.pipeline();
        pipeline.addLast("decoder", new StringDecoder());//chanel inbound handler
        pipeline.addLast("encoder", new StringEncoder());
        pipeline.addLast("handler", new TCPServerHandler());

    }

}

这是我处理httprequest和string的处理程序。但我的处理程序从不处理httprequest数据包。

class TCPServerHandler extends SimpleChannelInboundHandler<Object> {
    private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };

    private static final ChannelGroup channels = new DefaultChannelGroup("tasks", GlobalEventExecutor.INSTANCE);                                                               

    @Override
    public void channelRead0(ChannelHandlerContext ctx, Object msg)
            throws Exception {       

         if (msg instanceof HttpRequest) {
             System.out.println("http request");
            HttpRequest req = (HttpRequest) msg;

            boolean keepAlive = HttpUtil.isKeepAlive(req);
            FullHttpResponse response = new DefaultFullHttpResponse(req.protocolVersion(), OK,Unpooled.wrappedBuffer(CONTENT));
            response.headers()
                    .set(CONTENT_TYPE, TEXT_PLAIN)
                    .setInt(CONTENT_LENGTH, response.content().readableBytes());

            if (keepAlive) {
                if (!req.protocolVersion().isKeepAliveDefault()) {
                    response.headers().set(CONNECTION, KEEP_ALIVE);
                }
            } else {
                // Tell the client we're going to close the connection.
                response.headers().set(CONNECTION, CLOSE);
            }

            ChannelFuture f = ctx.write(response);

            if (!keepAlive) {
                f.addListener(ChannelFutureListener.CLOSE);
            }
        }

          if(msg instanceof String){
               System.out.println("String request");
            String arg1=(String)msg;
            Channel currentChannel = ctx.channel();
        if(arg1.equals("quit")){
            System.out.println("[INFO] - " + currentChannel.remoteAddress() + " is quitting... ");
        }else{
        System.out.println("[INFO] - " + currentChannel.remoteAddress() + " - "+ arg1);
        currentChannel.writeAndFlush("Server Said Hii "+ arg1);
        }
        }
    }

}

共有1个答案

卫招
2023-03-14

我认为不可能将同一个服务器引导配置为同时处理HTTP请求和原始字符串消息。您需要两个服务器引导(一个用于HTTP,一个用于字符串消息),每个都有自己的管道。您已经拥有用于字符串消息处理的解码器/编码器。

EventLoopGroup producer = new NioEventLoopGroup();
EventLoopGroup consumer = new NioEventLoopGroup();
ServerBootstrap httpSb = new ServerBootstrap();
ServerBootstrap strSb  = new ServerBootstrap();

httpSb.group(producer, consumer).bind(<port for http>).<other methods>...
strSb.group(producer, consumer).bind(<port for strings>).<other methods>...

对于HTTP,您需要添加处理程序HttpServerCodecHttpObjectAggregator,以便能够从通道读取FullHttpRequest,并将FullHttpResponse写入通道。

(聚合器是可选的,它可以帮助您避免将碎片化的传入HTTP数据合并到单个(完整)HTTP请求中的任务,以及将组合(完整)HTTP响应写入通道)

在HTTP引导程序中:

ch.pipeline().addLast("httpcodec"     , new HttpServerCodec());
ch.pipeline().addLast("httpaggregator", new HttpObjectAggregator(512 * 1024));
ch.pipeline().addLast("yourhandler"   , new YourHttpRequestHandler());

FullHttpRequest处理程序示例:

public class YourHttpRequestHandler extends ChannelInboundHandlerAdapter  {


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg_arg) 
    {
            FullHttpRequest msg = (FullHttpRequest)msg_arg;

            System.out.println("URI: " + msg.getUri());
            System.out.println("method: " + msg.getMethod().toString());
            System.out.println("protocol version: " + msg.getProtocolVersion()); 
            System.out.println("header1: " + msg.headers().get("header1"));
            System.out.println("header2: " + msg.headers().get("header2"));
            System.out.println("header3: " + msg.headers().get("header3"));
            System.out.println("content: " + msg.content().toString(CharsetUtil.UTF_8));

    }//end read

}//end handler
 类似资料:
  • 我想用Netty ChannelHandler用Gzip压缩和解压,我试了一段时间,但总是有点困难。我的代码如下: 有什么问题吗?

  • 我正在尝试使用Reactor Netty TcpClient以反应方式与主机交互,这可能是无法访问的。下面是通道初始化逻辑的示例: 我收到的输出: “inbound”和“outbound”有一个专门的方法来处理它们的错误,但是它们工作在一个连接实例之上,如果您得到“Connection timeout”,则不会创建该连接实例。 我试过: > 异常,我接收到的异常包装在“ErrorCallBacKn

  • 问题内容: 有人问我这个问题: 根据以上详细信息,在以下代码的println语句之前创建了多少String对象和多少参考变量? 我的回答是,此代码片段的结果是spring winter spring summer 有两个参考变量s1和s2。总共创建了八个String对象,如下所示:“ spring”,“ summer”(丢失),“ spring summer”,“ fall”(丢失),“ spri

  • 我们正在Netty之上实现SSL。但是当前的设计有一个缺陷。如果失败,客户端将重试连接到服务器。这是网络或服务器负载过重问题所需要的。但是错误的客户端凭据会导致持续的失败。 有一些解决办法: 客户端-服务器连接可以故障转移到未加密模式(从管道中删除SslHandler)。 客户端可以死亡并在知道它是SSL异常时抛出异常。 不幸的是,我不知道如何使用Netty实现这一点。几个问题: < li >如何

  • 我只能收到 如何处理

  • 本文向大家介绍如何在Java中处理Selenium中的代理?,包括了如何在Java中处理Selenium中的代理?的使用技巧和注意事项,需要的朋友参考一下 我们可以借助PROXY类在Java中使用Selenium处理代理。