Netty http协议开发应用

Http协议概述 

 

 1.什么是Http协议

  HTTP是一个属于【应用层】的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。

 

 2.HTTP协议的主要特点

   1) 支持Client/Server模式

   2)简单--客户向服务器请求,只需指定服务URL,携带必要的请求参数或者消息体

   3) 灵活---HTTP允许输任意类型的数据对象

  4)无状态--HTTP协议是无状态协议,无状态是指协议对于事务处理没有记忆能力。

 

3 HTTP协议的URL

  HTTP url(URL 是一种特殊类型的URL,包含了用查找某个资源的足够信息) 

  http://host[":"port][abs_path]

其中,http表示要通过HTTP协议来定位网络资源;host表示合法的Internet主机域名或者IP地址:port指定一个端口号,为空则使用默认端口80;abs_pa出指定请求资源的URI,如果URL中没有给出abs_path,那么当它作为请求URI时,必须以/的形式给出,通常这点工作浏览器会自动帮我们完成。

 

4http请求消息(HttpRequest)

 4.1http请求由三部分组成 如下
  HTTP请求行;
  HTTP消息头;
  HTTP请求正文;

     4.1.1HTTP请求行

     请求行以一个方法符开头,以空格分开,后面跟着请求的URL和协议的版本,格式为:
Metchod  Request-URL  HTTP-Version  CRLF

   Metchod 表示请求方法

   Request-URL 是一个统一资源标识符

   HTTP-Version 表示请求的HTTP协议版本

   CRLF 表示回车和换行

 

  Metchod 表示请求方法,各方法作用 :

1 新建实体类,这里需要实现 Serializable 接口即可

import java.io.Serializable;

public class GirlResponse implements Serializable {
    private static final long serialVersionUID = -2619994978640439932L;
    private int code;
    private String msg;

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

2 服务端的开发

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.http.HttpObject;

import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

import java.net.InetSocketAddress;

public class Server {
    public void bind(int port) throws InterruptedException
    {
        EventLoopGroup boss=new NioEventLoopGroup();
        EventLoopGroup worker=new NioEventLoopGroup();
        try
        {
            ServerBootstrap b=new ServerBootstrap();
            b.group(boss,worker)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1280)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>()
                    {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception
                        {
                            ch.pipeline().addLast(
                                    new ServerHandler()
                            );
                        }
                    });

            ChannelFuture f=b.bind(port).sync();

            f.channel().closeFuture().sync();
        } finally
        {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws InterruptedException
    {
        int port = 8006;
        new Server().bind(port);
    }
}

2.1 服务端服务处理

import com.fasterxml.jackson.core.io.CharTypes;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class ServerHandler extends ChannelInboundHandlerAdapter
{
    @Override
    public void channelRead(ChannelHandlerContext ctx , Object msg) throws Exception
    {
        UserInfo user= (UserInfo) msg;
        System.out.println("收到:"+user);
        ctx.writeAndFlush(reply(user));
    }

    private static GirlResponse reply(UserInfo user){
        GirlResponse gr=new GirlResponse();
        gr.setMsg("to "+user.getName()+" : 测试");
        return gr;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx , Throwable cause) throws Exception
    {
        cause.printStackTrace();
        ctx.close();
    }
}

3 客户端

import io.netty.bootstrap.Bootstrap;
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.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
public class Client {

    public void connect(int port, String host) throws InterruptedException
    {
        EventLoopGroup group = new NioEventLoopGroup();
        try
        {
            Bootstrap b=new Bootstrap();
            b.group(group)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>()
                    {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception
                        {

                            ch.pipeline().addLast(new ClientHandler());
                        }
                    });

            ChannelFuture f= b.connect(host, port).sync();
            f.channel().closeFuture().sync();
        } finally
        {
            group.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws InterruptedException
    {
        int port = 8006;
        String host="127.0.0.1";
        new Client().connect(port, host);
    }

}

3.1 客户端实现类

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import java.util.Random;

public class ClientHandler extends ChannelInboundHandlerAdapter {

    public void channelActive(ChannelHandlerContext ctx) throws Exception
    {
        System.out.println("同学测试:");
        Random r = new Random();
        for (int i = 1; i <= 5; i++)
        {
            UserInfo user = new UserInfo();
            user.setName("同学 " + i);
            user.setHeight(r.nextInt(25) + 160);
            ctx.write(user);
            System.out.println(user);
        }
        ctx.flush();
    }


    public void channelRead(ChannelHandlerContext ctx , Object msg) throws Exception
    {
        GirlResponse gr= (GirlResponse) msg;
        System.out.println("收到测试回复 :"+gr.getMsg());
    }

    public void exceptionCaught(ChannelHandlerContext ctx , Throwable cause) throws Exception
    {
        cause.printStackTrace();
        ctx.close();
    }
}

4运行结果

同学测试:
[name=同学 1, height=182]
[name=同学 2, height=165]
[name=同学 3, height=173]
[name=同学 4, height=163]
[name=同学 5, height=177]

 
   
   
   
   
   
   
   
   

 

4.1.2HTTP消息头 列表

名称 作用
Accept

请求报头域用于指定客户端接受那些类型的信息

如: image/gif

Accept-Charset 请求报头域用于指定客户端接受的字符集
Accept-Encoding 请求报头域 类似于Accept,但是它用于指定可接受的内容编码
Accept-Language 请求报头域 类似于Accept,但是它用于指定一种自然语言
Authorization 请求报头域 主要用于证明客户端有权查看 某个资源
Host

发送请求时,该报头域是必需的,用于指定被请求资源的Internet主机和端口号

它通用是从HTTPURL中提取出来

User-Agent 请求报头域允许客户端将它的操作系统,浏览器和其他属性告诉服务器
content-Length 请求消息体的长度
Content-Type 表示后面的文档属于什么MIME 类型 如 text/html
Connection 连接类型

5 HTTP 响应消息(HttpResponse)

    http响应由三个部分组成分别是状态行,响应头,响应正文。

    状态行是由:HTTP-Version, Status-Code,Reason-Phrase CRLF

 分别表示:http版本 + 状态码 + 状态代码的文本描述

    HTTP-Version:表示服务器HTTP协议的版本

    Status-Code: 服务器返回的响应状态代码

 状态代码

1xx 指示信息–表示请求已接收,继续处理
2xx 成功–表示请求已被成功接收、理解、接受
3xx 重定向–要完成请求必须进行更进一步的操作。
4xx 客户端错误–请求有语法错误或请求无法实现。
5xx 服务器端错误–服务器未能实现合法的请求。
响应头:包含服务器类型,日期,长度,内容类型等。

5 Netty http实列:

 5.1 Netty Serverr

import com.jboss.MarshallingCodeCFactory;
import com.netty.Serverr;
import com.sun.jndi.toolkit.url.Uri;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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.LineBasedFrameDecoder;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpRequestEncoder;
import io.netty.handler.codec.http.HttpResponseDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.apache.log4j.spi.Configurator;
import sun.security.krb5.Config;

public class HttpServerText {

public void bind(int port) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();

try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new HttpResponseEncoder());
ch.pipeline().addLast(new HttpResponseDecoder());
ch.pipeline().addLast(new HttpServerHandler());
}
});

ChannelFuture sync = bootstrap.bind(port).sync();
sync.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}

public static void main(String[] args) throws Exception {

new HttpServerText().bind(8081);
}
}

 5.2 Netty Serverr 响应请求

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import org.apache.http.HttpConnection;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpHeaders.Values;


public class HttpServerHandler extends ChannelInboundHandlerAdapter {

private HttpRequest request;

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
{
if(msg instanceof HttpRequest)
{

request=(HttpRequest)msg;
System.out.println("Uri:" + request.uri());
}
if(msg instanceof HttpContent)
{
HttpContent content = (HttpContent) msg;
ByteBuf buf = content.content();
System.out.println(buf.toString(io.netty.util.CharsetUtil.UTF_8));
buf.release();
//HttpVersion.HTTP_1_1: http版本
//HttpResponseStatus.OK: http响应状态码
String res="OK";
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(res.getBytes("UTF-8")));
//设置内容类型
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
//设置内容长度
response.headers().set(HttpHeaderNames.CONTENT_LENGTH,response.content().readableBytes());
//开始给浏览器回复消息
ctx.write(response);
ctx.flush();

}

}


public void channelReadComplete(ChannelHandlerContext context) throws Exception
{

context.flush();
}

@Override
public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
System.out.println(cause.getMessage());
context.close();
}
}

结果

浏览器:  http://127.0.0.1:8081/

posted on 2020-09-21 15:09  shumeigang  阅读(200)  评论(0)    收藏  举报

导航