您的位置:首页 > 编程语言 > Java开发

Netty学习笔记(六)Springboot实现基于http协议的简单服务器---浏览器和客户端访问

2019-04-03 12:34 916 查看

参考文章: https://www.geek-share.com/detail/2708436881.html

上代码

  1. 建服务器启动类EchoServer

    public class EchoServer {
    private final int port;
    private Logger log = LoggerFactory.getLogger(this.getClass());
    
    public EchoServer(int port)
    {
    this.port=port;
    }
    
    public void start() throws Exception{
    final EchoServerHandler serverHandler = new EchoServerHandler();
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    
    try
    {
    ServerBootstrap b = new ServerBootstrap();
    b.group(bossGroup, workerGroup)
    .localAddress(new InetSocketAddress(port))
    .channel(NioServerSocketChannel.class)
    .childHandler(new ChannelInitializer<SocketChannel>() {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
    ch.pipeline().addLast(new HttpRequestDecoder());
    ch.pipeline().addLast(new HttpObjectAggregator(65535));
    ch.pipeline().addLast(new HttpResponseEncoder());
    ch.pipeline().addLast(new ReadTimeoutHandler(5)); //5秒没有读事件就关掉
    ch.pipeline().addLast(new ClientHandler());
    }
    });
    ChannelFuture f=b.bind().sync();
    f.channel().closeFuture().sync();
    }
    finally {
    workerGroup.shutdownGracefully();
    bossGroup.shutdownGracefully();
    }
    }
    }
    提醒一句:博主这个服务器是长连接,如果没有ReadTimeoutHandler的话,是一直一直连接着的,即使你关了浏览器
  2. ClientHandler类:

    @ChannelHandler.Sharable
    public class ClientHandler extends ChannelInboundHandlerAdapter {
    private ByteBufToBytes reader;
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{
    if (msg instanceof HttpRequest) {
    HttpRequest request = (HttpRequest) msg;
    System.out.println("messageType:"+ request.headers().get("messageType"));
    System.out.println("businessType:"+ request.headers().get("businessType"));
    if (HttpUtil.isContentLengthSet(request)) {
    reader = new ByteBufToBytes(
    (int) HttpUtil.getContentLength(request));
    }
    }
    if (msg instanceof HttpContent) {
    HttpContent httpContent = (HttpContent) msg;
    ByteBuf content = httpContent.content();
    reader.reading(content);
    content.release();
    if (reader.isEnd()) {
    String resultStr = new String(reader.readFull());
    //String resultStr = java.net.URLDecoder.decode(s,"utf-8");     转码
    System.out.println("Client said:" + resultStr);
    
    //这里大家可以封装一下
    FullHttpResponse response = new DefaultFullHttpResponse(
    HTTP_1_1, OK, Unpooled.wrappedBuffer("I am ok"
    .getBytes()));
    
    //博主其实不是很理解这个两种方式的区别,知道的可以留言告诉我
    /*	FullHttpResponse response = new DefaultFullHttpResponse(
    HTTP_1_1, OK, Unpooled.copiedBuffer(message, UTF_8)); */
    
    response.headers().set(CONTENT_TYPE, "text/plain");
    
    //允许跨域访问(网页端)
    response.headers().set(ACCESS_CONTROL_ALLOW_ORIGIN,"*");
    response.headers().set(ACCESS_CONTROL_ALLOW_HEADERS,"Origin, X-Requested-With, Content-Type, Accept");
    response.headers().set(ACCESS_CONTROL_ALLOW_METHODS,"GET, POST, PUT,DELETE");
    
    response.headers().set(CONTENT_LENGTH,
    response.content().readableBytes());
    response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE);
    //发送给客户端,网页端
    ctx.write(response);
    ctx.flush();
    }
    }
    }
  3. 数据处理ByteBufToBytes

    public class ByteBufToBytes {
    private ByteBuf temp;
    private boolean end = true;
    public ByteBufToBytes(int length) {
    temp = Unpooled.buffer(length);
    }
    public void reading(ByteBuf datas) {
    datas.readBytes(temp, datas.readableBytes());
    if (this.temp.writableBytes() != 0) {
    end = false;
    } else {
    end = true;
    }
    }
    public boolean isEnd() {
    return end;
    }
    public byte[] readFull() {
    if (end) {
    byte[] contentByte = new byte[this.temp.readableBytes()];
    this.temp.readBytes(contentByte);
    this.temp.release();
    return contentByte;
    } else {
    return null;
    }
    }
    public byte[] read(ByteBuf datas) {
    byte[] bytes = new byte[datas.readableBytes()];
    datas.readBytes(bytes);
    return bytes;
    }
    }
  4. appliction:

    @SpringBootApplication
    public class ServerApplication implements CommandLineRunner {
    
    public static void main(String[] args) {
    SpringApplication.run(ServerApplication.class, args);
    }
    
    @Override
    public void run(String... strings) throws Exception {
    EchoServer echoServer = new EchoServer(7000);
    echoServer.start();
    }
    }

——————————————————我是分割线,下面是客户端——————————————————————————

  1. 启动类EchoClient :

    public class EchoClient {
    @Value("${netty.host}")
    private String host;
    @Value("${netty.port}")
    private int port;
    
    public void start() throws Exception {
    EventLoopGroup group = new NioEventLoopGroup();
    
    try {
    Bootstrap b = new Bootstrap();
    b.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(host, port))
    .handler(new ChannelInitializer<Channel>() {
    @Override
    protected void initChannel(Channel ch) throws Exception {
    ch.pipeline().addLast(new HttpResponseDecoder());
    ch.pipeline().addLast(new HttpRequestEncoder());
    ch.pipeline().addLast(new EchoClientHandler());
    }
    });
    ChannelFuture f = b.connect().sync();
    
    URI uri = new URI("http://127.0.0.1:7000");
    String msg = "Are you ok?";
    DefaultFullHttpRequest request = new DefaultFullHttpRequest(
    HttpVersion.HTTP_1_1, HttpMethod.POST, uri.toASCIIString(),
    Unpooled.wrappedBuffer(msg.getBytes()));
    // 构建http请求
    request.headers().set(HttpHeaderNames.HOST, host);
    request.headers().set(HttpHeaderNames.CONNECTION,
    HttpHeaderNames.CONNECTION);
    request.headers().set(HttpHeaderNames.CONTENT_LENGTH,
    request.content().readableBytes());
    request.headers().set("messageType", "normal");
    request.headers().set("businessType", "testServerState");
    // 发送http请求
    f.channel().write(request);
    f.channel().flush();
    
    f.channel().closeFuture().sync();
    } finally {
    group.shutdownGracefully().sync();
    }
    }
    }
  2. Handler类:

    @ChannelHandler.Sharable
    public class EchoServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{
    ByteBuf in = (ByteBuf) msg;
    System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8));
    ctx.write(in);
    }
    
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    //服务端接收到客户端上线通知
    Channel incoming = ctx.channel();
    System.out.println("SimpleChatClient:" + incoming.remoteAddress()+"在线");
    }
    
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx){
    ctx.writeAndFlush(ChannelFutureListener.CLOSE);
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause){
    cause.printStackTrace();
    ctx.close();
    }
    }
  3. ByteBufToBytes类,和上面一样的

  4. application:

    @SpringBootApplication
    public class ClientHttpApplication implements CommandLineRunner {
    @Autowired
    private EchoClient echoclient;
    
    public static void main(String[] args) {
    SpringApplication.run(ClientHttpApplication.class, args);
    }
    
    @Bean           //凡是子类及带属性、方法的类都注册Bean到Spring中,交给它管理;
    public EchoClient echoClient(){
    return new EchoClient();
    }
    
    @Override
    public void run(String... strings) throws Exception {
    //EchoClient echoclient = new EchoClient();
    echoclient.start();
    }
    }

————————————————————网页端测试,随便写个ajax————————————————————————

<!DOCTYPE html>
<html>
<head>
<script
1c140
type="text/javascript" src=jquery-1.8.0.min.js></script>
<meta charset="UTF-8">
<title>sample page</title>
</head>
<body>

<input type="text" id="message">
<input type="button" value="发送消息" "sendMsg()">
<br/>
接收到消息:
<p id="server_message" style="background-color: #AAAAAA"></p>
<script type="text/javascript"S>

function sendMsg(){
//location.reload()

$.ajax({
url: "http://127.0.0.1:7000",
data: {name:3},
type: 'post',
success: function(result){
alert(result);
}
});

}
</script>
</body>
</html>

结语

大家可以根据需要添加些进阶功能

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: