Netty简单示例实现http

该文展示了如何使用Netty框架创建TCP服务器和客户端,以及HTTP服务器。服务端接收到TCP消息后会连续发送多个响应,而HTTP服务器则处理GET请求并返回相应的内容。客户端部分包括TCP连接发送消息和HTTP请求的示例。
摘要由CSDN通过智能技术生成

一、tcp

服务端:

package com.zhk.swagger.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.nio.charset.StandardCharsets;

public class NettyServer {

    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap()
                    .group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(new SimpleChannelInboundHandler<ByteBuf>() {
                                @Override
                                protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
                                    String str = msg.toString(StandardCharsets.UTF_8);
                                    System.out.println("收到消息 " + str);
                                    Integer num = 0;
                                    while (num < 1000) {
                                        ctx.writeAndFlush(Unpooled.copiedBuffer("发送消息中::" + num, StandardCharsets.UTF_8));
                                        num++;
                                        if (num % 100 == 0) {
                                            ctx.flush(); // 每发送100条消息,强制刷新缓冲区
                                        }
                                    }
                                    ctx.writeAndFlush(Unpooled.copiedBuffer("发送消息完成", StandardCharsets.UTF_8)).addListener(future -> {
                                        if (future.isSuccess()) {
                                            System.out.println("消息已经发送完成,关闭连接");
                                            ctx.channel().close();
                                        }
                                    });
                                }
                            });
                        }
                    });
            ChannelFuture future = bootstrap.bind(8000).sync();
            System.out.println("Server started, listening on port 8000.");
            future.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}


客户端

package com.zhk.swagger.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;

public class NettySender {

    public static void main(String[] args) throws Exception {
        NioEventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap()
                .group(group)
                .channel(NioSocketChannel.class)
                .handler(new SimpleChannelInboundHandler<ByteBuf>() {
                    @Override
                    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
                        String str = msg.toString(StandardCharsets.UTF_8);
                        System.out.println("Received message: " + str);
                    }
                });

        ChannelFuture future = bootstrap.connect(new InetSocketAddress("localhost", 8000)).sync();

        ByteBuf message = Unpooled.copiedBuffer("Hello, server!", StandardCharsets.UTF_8);
        future.channel().writeAndFlush(message);

        future.channel().closeFuture().sync();
        group.shutdownGracefully();
    }
}


http

服务端


public class NettyHttpServer {

    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline p = ch.pipeline();
                     p.addLast(new HttpServerCodec());
                     p.addLast(new HttpObjectAggregator(1024 * 1024));
                     p.addLast(new SimpleChannelInboundHandler<FullHttpRequest>() {
                         @Override
                         protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
                             String uri = request.uri();
                             if ("/hello".equals(uri)) {
                                 String content = "Hello, Netty!";
                                 FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
                                         Unpooled.copiedBuffer(content, CharsetUtil.UTF_8));
                                 response.headers().set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN);
                                 response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
                                 ctx.writeAndFlush(response);
                             } else {
                                 FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND);
                                 ctx.writeAndFlush(response);
                             }
                         }
                     });
                 }
             })
             .option(ChannelOption.SO_BACKLOG, 128)
             .childOption(ChannelOption.SO_KEEPALIVE, true);

            // Start the server.
            ChannelFuture f = b.bind(8000).sync();

            // Wait until the server socket is closed.
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}



http请求http://localhost:8000/hello

二、发送http请求

HTTP_1_1是可以一次tcp一次http请求的
HTTP_1_1是可以一次tcp多次http请求的

HttpClientExample

package com.zhk.study.test;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpContentDecompressor;
import io.netty.util.CharsetUtil;

public class HttpClientExample {
    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap()
                .group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new HttpClientCodec());
                        ch.pipeline().addLast(new HttpContentDecompressor());
                        ch.pipeline().addLast(new HttpObjectAggregator(65536));
                        ch.pipeline().addLast(new HttpClientHandler());
                    }
                });

            ChannelFuture future = bootstrap.connect("localhost", 9999).sync();
            
            // 第一个 HTTP 请求
            HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/hi");
            //设置地址
            request.headers().set(HttpHeaders.Names.HOST, "localhost");
            future.channel().writeAndFlush(request);


			// 第二个 HTTP 请求 
            HttpRequest request2 = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/download2");
            request2.headers().set(HttpHeaders.Names.HOST, "localhost");
            //主动断开的话需要加上就是不发送请求了
            //request2.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE); // 添加Connection: close头部

            future.channel().writeAndFlush(request2);
            future.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}

HttpClientHandler

package com.zhk.study.test;

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

public class HttpClientHandler extends SimpleChannelInboundHandler<FullHttpResponse> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpResponse response) throws Exception {

        System.out.println("HTTP Response Status: " + response.status());
        System.out.println("Response Content: " + response.content().toString(CharsetUtil.UTF_8));

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单Netty WebSocket 示例代码: ```java import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.websocketx.WebSocketFrameAggregator; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import io.netty.handler.stream.ChunkedWriteHandler; import io.netty.util.concurrent.DefaultThreadFactory; public class WebSocketServer { private static final int PORT = 8080; public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("boss")); EventLoopGroup workerGroup = new NioEventLoopGroup(0, new DefaultThreadFactory("worker")); try { ServerBootstrap bootstrap = new ServerBootstrap() .group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpObjectAggregator(65536)); pipeline.addLast(new ChunkedWriteHandler()); pipeline.addLast(new WebSocketFrameAggregator(65536)); pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); pipeline.addLast(new WebSocketServerHandler()); } }); Channel ch = bootstrap.bind(PORT).sync().channel(); System.out.println("WebSocket server started at port " + PORT + "."); System.out.println("Open your browser and navigate to http://localhost:" + PORT + "/"); ch.closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } ``` 上述代码创建了一个 Netty WebSocket 服务器,监听端口为 8080。新连接会通过 `ChannelInitializer` 进行处理,其中添加了以下几个处理器: - `HttpServerCodec`:用于将 HTTP 请求和响应编解码为 Netty 的 `HttpRequest` 和 `HttpResponse` 对象。 - `HttpObjectAggregator`:用于将 HTTP 消息的多个部分合并成一个完整的消息。 - `ChunkedWriteHandler`:用于处理大文件或者大数据流,将数据以块(Chunk)的形式写入到客户端。 - `WebSocketFrameAggregator`:用于将 WebSocket 帧的多个部分合并成一个完整的帧。 - `WebSocketServerProtocolHandler`:用于处理 WebSocket 握手和帧的编解码。 - `WebSocketServerHandler`:自定义的处理器,用于处理客户端的 WebSocket 帧。 `WebSocketServerHandler` 的示例代码如下: ```java import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import io.netty.handler.codec.http.websocketx.WebSocketFrame; import io.netty.handler.codec.http.websocketx.WebSocketFrameAggregator; public class WebSocketServerHandler extends SimpleChannelInboundHandler<WebSocketFrame> { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client connected: " + ctx.channel().remoteAddress()); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client disconnected: " + ctx.channel().remoteAddress()); } @Override protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception { if (frame instanceof TextWebSocketFrame) { String text = ((TextWebSocketFrame) frame).text(); System.out.println("Received message: " + text); ctx.channel().writeAndFlush(new TextWebSocketFrame("Server received: " + text)); } else { throw new UnsupportedOperationException("Unsupported frame type: " + frame.getClass().getName()); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { System.err.println("Exception caught: " + cause.getMessage()); ctx.close(); } } ``` 上述代码实现了 `SimpleChannelInboundHandler` 接口,用于处理客户端发送的 WebSocket 帧。当收到 `TextWebSocketFrame` 类型的帧时,会将其内容打印到控制台,并将其转发给客户端。其他类型的帧会抛出异常。 客户端可以通过 JavaScript 代码连接到服务器: ```javascript let socket = new WebSocket("ws://localhost:8080/ws"); socket.onopen = function() { console.log("Connected to WebSocket server."); socket.send("Hello, WebSocket server!"); }; socket.onmessage = function(event) { console.log("Received message: " + event.data); }; socket.onclose = function(event) { console.log("Disconnected from WebSocket server."); }; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张航柯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值