package com.fangliang.proxy_server.start;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
@Component
public class StartServer {
@EventListener(ApplicationReadyEvent.class)
public void start() {
//处理io事件 的线程组
EventLoopGroup group = new NioEventLoopGroup();
try {
//服务端启动器
ServerBootstrap bootstrap = new ServerBootstrap();
//设置线程组
bootstrap.group(group)
//设置服务端通道 负责监听客户端的连接请求
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//设置通道的处理器
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new StringDecoder());// pipelineHandler 添加处理器 解码器
pipeline.addLast(new StringEncoder()); // pipelineHandler 添加处理器 编码器
pipeline.addLast(new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
System.out.println("read msg : " + s);
String responseBody = "<<!DOCTYPE html>\n" +
"<html lang=\"zh-CN\">\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +
" <title>示例页面</title>\n" +
"</head>\n" +
"<body>\n" +
" <h1>欢迎访问示例页面</h1>\n" +
" <p>这是一个简单的HTML页面,用于演示HTTP响应。</p>\n" +
"</body>\n" +
"</html>";
byte[] responseBytes = responseBody.getBytes(StandardCharsets.UTF_8);
int contentLength = responseBytes.length;
ctx.writeAndFlush("HTTP/1.1 200 OK\r\n" +
"Date: Fri, 13 Sep 2024 10:00:00 GMT\r\n" +
"Server: Apache/2.4.57 (Win64) OpenSSL/1.1.1w\r\n" +
"Content-Type: text/html; charset=UTF-8\r\n" +
"Content-Length: " + contentLength + "\r\n" +
"Connection: keep-alive\r\n" +
"Cache-Control: no-cache, no-store, must-revalidate\r\n" +
"Pragma: no-cache\r\n" +
"Expires: 0\r\n" +
"Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure\r\n" +
"X-Frame-Options: DENY\r\n" +
"X-XSS-Protection: 1; mode=block\r\n" +
"X-Content-Type-Options: nosniff\r\n" +
"Strict-Transport-Security: max-age=31536000; includeSubDomains\r\n" +
"Referrer-Policy: strict-origin-when-cross-origin\r\n" +
"\r\n" + // 空行分隔头部和响应体
responseBody);
}
});
}
});
ChannelFuture sync = bootstrap.bind(8081).sync();
System.out.println("server start-----------");
sync.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
}finally {
group.shutdownGracefully();
}
}
}
效果: