ネッティーは、単純なHTTPサーバーを実装します

クライアントはブラウザがあるので、これだけサーバーを記述する必要があります

サーバー:バインドポート10086

package com.jym.http;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @program: NettyPro
 * @description: 服务端,简单实现http
 * @author: jym
 * @create: 2020/02/08
 */
public class TestSever {
    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup,workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new TestSeverInitializer());

            ChannelFuture channelFuture = serverBootstrap.bind(10086).sync();

            channelFuture.addListener(new ChannelFutureListener() {
                public void operationComplete(ChannelFuture channelFuture)  {
                    if(channelFuture.isSuccess()){
                        System.out.println("监听端口 10086 成功");
                    } else {
                        System.out.println("监听端口失败");
                    }
                }
            });
            channelFuture.channel().closeFuture().sync();

        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }
}

継承ChannelInitializerオーバーライドメソッドにカスタム初期化の必要性:

package com.jym.http;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;

/**
 * @program: NettyPro
 * @description:
 * @author: jym
 * @create: 2020/02/08
 */
public class TestSeverInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        // 向管道加入处理器
        //得到管道
        ChannelPipeline pipeline = socketChannel.pipeline();
        // 加入一个netty提供的httpServer codec
        // HttpServerCodec说明
        // 1.netty提供的一个http的编--解码器
        pipeline.addLast("JymHttpSeverCodec",new HttpServerCodec());
        // 增加自定义的处理器
        pipeline.addLast("JymHttpSeverHandler",new TestHttpSeverHandler());
    }

}

ブラウザは、2つの要求、通常のリクエストを送信しますので、カスタムハンドラは、ページのアイコンが別々に処理されます

package com.jym.http;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;

/**
 * @program: NettyPro
 * @description: 处理器,SimpleChannelInboundHandler说明:
 * 1.是ChannelInboundHandlerAdapter的子类
 * 2.HttpObject 客户端和服务器端相互通讯的数据被封装成 HttpObject
 * @author: jym
 * @create: 2020/02/08
 */
public class TestHttpSeverHandler extends SimpleChannelInboundHandler<HttpObject> {

    private static byte[] bytes;

    static {
        File file = new File("D:\\壁纸\\LOL\\1.jpg");
        FileInputStream fi = null;
        try {
            long fileSize = file.length();
            if (fileSize > Integer.MAX_VALUE) {
                throw new IOException(file.getName()+"file too big... ");
            }
            fi = new FileInputStream(file);
            bytes = new byte[(int) fileSize];
            int offset = 0;
            int numRead = 0;
            while (offset < bytes.length
                    && (numRead = fi.read(bytes, offset, bytes.length - offset)) >= 0) {
                offset += numRead;
            }
            // 确保所有数据均被读取
            if (offset != bytes.length) {
                throw new IOException("Could not completely read file "
                        + file.getName());
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fi!=null){
                try {
                    fi.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取客户端数据
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject httpObject) throws Exception {
        // 判断 httpObject 是不是一个HttpRequest请求
        if(httpObject instanceof HttpRequest){
            System.out.println("msg 类型:"+ httpObject.getClass());
            System.out.println("客户端地址:"+channelHandlerContext.channel().remoteAddress());

            HttpRequest request = (HttpRequest)httpObject;
            URI uri = new URI(request.uri());
            ByteBuf content = null;
            // 处理图标
            if("/favicon.ico".equals(uri.getPath())){
                content = Unpooled.copiedBuffer(bytes);
            } else {
                // 回复信息给浏览器
                content = Unpooled.copiedBuffer("hello,我是服务器", CharsetUtil.UTF_8);
            }
            // 构造一个 httpResponse
            DefaultFullHttpResponse response =
                    new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,content);
            // 设置响应头
            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());

            channelHandlerContext.writeAndFlush(response);
        }
    }

}

SimpleChannelInboundHandler説明:
1. ChannelInboundHandlerAdapterはのサブクラスである
データ2.HttpObjectクライアントとサーバの相互に通信がHttpObjectパックされ

テスト結果:

サーバを起動した後、アクセスポート10086:
ここに画像を挿入説明
アイコンとコンテンツが表示正しく

悪いの学習時間の不足、あまりにも浅い知識は、ご容赦ください。

人々の10種類が世界であり、1は、1つのバイナリを理解していないで、バイナリを理解することです。

公開された71元の記事 ウォン称賛54 ビュー420 000 +

おすすめ

転載: blog.csdn.net/weixin_43326401/article/details/104229005