`
hbxflihua
  • 浏览: 679373 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Netty HTTP协议简单实现

阅读更多

HTTP(超文本传输协议)协议是建立在TCP传输协议之上的应用层协议,它的发展是万维网协会和Internet工作小组IETF合作的结果。HTTP是一个属于应用层的面向对象的协议,由于其简洁、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过多年的使用和发展,得到了不断的完善和扩展。本文将介绍如何基于Netty 的HTTP协议栈进行HTTP服务端和客户端的开发。由于Netty的HTTP协议栈是基于Netty的NIO通信框架开发的,因此,Netty的HTTP协议也是异步非阻塞的。

 

HTTP服务端开发

 

HttpFileServer.java

package emulator.http;

import emulator.Constants;
import io.netty.bootstrap.ServerBootstrap;
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.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;

/**
 * 模拟服务端
 * @author lh
 * @date 2015-08-11 14:33
 * @version 1.0
 * 
 */
public class HttpFileServer {

	public void run(final int port) 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
						protected void initChannel(SocketChannel ch)
								throws Exception {
							// 服务端,对请求解码
							ch.pipeline().addLast("http-decoder",
									new HttpRequestDecoder());
							// 聚合器,把多个消息转换为一个单一的FullHttpRequest或是FullHttpResponse
							ch.pipeline().addLast("http-aggregator",
									new HttpObjectAggregator(65536));
							// 服务端,对响应编码
							ch.pipeline().addLast("http-encoder",
									new HttpResponseEncoder());
							// 块写入处理器
							ch.pipeline().addLast("http-chunked",
									new ChunkedWriteHandler());
							// 自定义服务端处理器
							ch.pipeline().addLast("fileServerHandler",
									new HttpFileServerHandler());
						}
					});
			ChannelFuture future = b.bind(Constants.DEFAULT_IP, port).sync();
			System.out.println("HTTP文件目录服务器启动,网址是 : " + "http://" + Constants.DEFAULT_IP	+ ":" + port);
			future.channel().closeFuture().sync();
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}

	public static void main(String[] args) throws Exception {
		new HttpFileServer().run(Constants.DEFAULT_PORT);
	}
}

 

HttpFileServerHandler.java

package emulator.http;

import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;

import emulator.Constants;
import emulator.util.Dom4JUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.CharsetUtil;

/**
 * 模拟服务端处理器
 * @author lh
 * @date 2015-08-11 14:33
 * @version 1.0
 * 
 */
public class HttpFileServerHandler extends
		SimpleChannelInboundHandler<FullHttpRequest> {

	@Override
	public void messageReceived(ChannelHandlerContext ctx,
			FullHttpRequest request) throws Exception {
		
		if (!request.getDecoderResult().isSuccess()) {
			sendError(ctx, BAD_REQUEST);
			return;
		}
		
		ByteBuf buf =  request.content();
		byte [] req = new byte[buf.readableBytes()];  
        buf.readBytes(req);  
        String xml = new String(req,"UTF-8");  
        resp(ctx,xml);
	}
	
	/**
	 * 
	 * @param xml
	 */
	private void resp(ChannelHandlerContext ctx, String xml){
		String transCode = Dom4JUtil.header(xml, "transcode");
		String retUrl = "D:\\workspaces\\eclipse-huifu\\emulator\\xml\\error.xml";
		String retCtt = null;
		if(equal(transCode, Constants.TC_DZZH)){//电子账户
			
			retUrl = "D:\\workspaces\\eclipse-huifu\\emulator\\xml\\account\\manage\\resp.xml";
		
		}else if(equal(transCode, Constants.TC_YHKBD)){//银行卡绑定
			
		}
		
		try {
			retCtt = FileUtils.readFileToString(new File(retUrl));
		} catch (IOException e) {
			e.printStackTrace();
		}
		FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1,
				HttpResponseStatus.FOUND, Unpooled.copiedBuffer(retCtt, CharsetUtil.UTF_8));
		response.headers().set(CONTENT_TYPE, "text/xml; charset=UTF-8");
		ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
		
	}
	
	
	public static boolean equal(String var, String cons){
		return isNotEmpty(var) && cons.equals(var);		
	}
	
	private static boolean isNotEmpty(String s){
		return (null != s && !"".equals(s));
	}

	/**
	 * 错误处理
	 * @param ctx
	 * @param status
	 */
	private static void sendError(ChannelHandlerContext ctx,
			HttpResponseStatus status) {
		String ret =  null;
		FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1,
				status, Unpooled.copiedBuffer(ret, CharsetUtil.UTF_8));
		response.headers().set(CONTENT_TYPE, "text/xml; charset=UTF-8");
		ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
	}


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

}

 

 

HTTP客户端开发

 

HttpFileClient.java

package emulator.http;

import io.netty.bootstrap.Bootstrap;
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.NioSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestEncoder;
import io.netty.handler.codec.http.HttpResponseDecoder;
import io.netty.handler.stream.ChunkedWriteHandler;

import java.net.InetSocketAddress;

import emulator.Constants;

/**
 * 模拟客户端
 * 
 * @author lh
 * @date 2015-08-11 14:31
 * @version 1.0
 * 
 */
public class HttpFileClient {

	public void connect(int port) throws Exception {
		// 配置客户端NIO线程组
		EventLoopGroup group = new NioEventLoopGroup();
		try {
			Bootstrap b = new Bootstrap();
			b.group(group).channel(NioSocketChannel.class)
					.option(ChannelOption.TCP_NODELAY, true)
					.handler(new ChannelInitializer<SocketChannel>() {
						@Override
						public void initChannel(SocketChannel ch)
								throws Exception {

							// 客户端,对请求编码
							ch.pipeline().addLast("http-encoder",
									new HttpRequestEncoder());
							// 客户端,对响应解码
							ch.pipeline().addLast("http-decoder",
									new HttpResponseDecoder());
							// 聚合器,把多个消息转换为一个单一的FullHttpRequest或是FullHttpResponse
							ch.pipeline().addLast("http-aggregator",
									new HttpObjectAggregator(65536));
							// 块写入处理器
							ch.pipeline().addLast("http-chunked",
									new ChunkedWriteHandler());
							// 自定义客户端处理器
							ch.pipeline().addLast("fileClientHandler",
									new HttpFileClientHandler());

						}
					});

			// 发起异步连接操作
			ChannelFuture f = b.connect(new InetSocketAddress(port)).sync();

			// 当代客户端链路关闭
			f.channel().closeFuture().sync();

		} finally {
			// 优雅退出,释放NIO线程组
			group.shutdownGracefully();
		}
	}

	/**
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		new HttpFileClient().connect(Constants.DEFAULT_PORT);
	}
}

 

HttpFileClientHandler.java

package emulator.http;

import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.commons.io.FileUtils;

import emulator.Constants;
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.DefaultFullHttpRequest;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.util.CharsetUtil;

/**
 * 模拟客户端处理器
 * @author lh
 * @date 2015-08-11 14:32
 * @version 1.0
 * 
 */
public class HttpFileClientHandler extends
		SimpleChannelInboundHandler<FullHttpResponse> {

	@Override
	public void channelActive(ChannelHandlerContext ctx) {
		String xml = null;
		try {
			xml = FileUtils.readFileToString(new File("D:\\workspaces\\eclipse-huifu\\emulator\\xml\\account\\manage\\req.xml"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		URI uri = null;
		try {
			uri = new URI("http://"+Constants.DEFAULT_IP+":"+Constants.DEFAULT_PORT);
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		FullHttpRequest req = new DefaultFullHttpRequest(HTTP_1_1,
				HttpMethod.GET,uri.toASCIIString(), 
				Unpooled.copiedBuffer(xml, CharsetUtil.UTF_8));	
		
		req.headers().set(HttpHeaders.Names.HOST, Constants.DEFAULT_IP);
        req.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
        req.headers().set(HttpHeaders.Names.CONTENT_LENGTH, req.content().readableBytes());
		
		ctx.writeAndFlush(req);
	}

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

	@Override
	protected void messageReceived(ChannelHandlerContext ctx,
			FullHttpResponse msg) throws Exception {
		
		ByteBuf buf =  msg.content();
		byte [] resp = new byte[buf.readableBytes()];  
        buf.readBytes(resp);  
        String xml = new String(resp,"UTF-8");  
		System.out.println("server cotent:\n"+xml);
	}
}

 

Constants.java

package emulator;

public final class Constants {
	
	/**
	 * 电子账户
	 */
	public static final String TC_DZZH = "31001";
	/**
	 * 银行卡绑定
	 */
	public static final String TC_YHKBD = "31002";
	/**
	 * 客户充值
	 */
	public static final String TC_KHCZ = "31021";
	/**
	 * 协议管理
	 */
	public static final String TC_XYGL = "31004";
	/**
	 * 项目管理
	 */
	public static final String TC_XMGL = "31005";
	
	/**
	 * 交易成功
	 */
	public static final String TC_JYCG = "0000";
	
	/**
	 * 交易失败
	 */
	public static final String TC_JYSB = "0001";
	
	/**
	 * 部分成功
	 */
	public static final String TC_BFCG = "0002";
	
	
	/**
	 * 默认IP
	 */
	public static final String DEFAULT_IP = "192.168.1.64";
	/**
	 * 默认端口
	 */
	public static final int DEFAULT_PORT = 8080;	

}

 

分享到:
评论

相关推荐

    Netty TCP协议简单实现

    在本文中,我们将深入探讨如何使用 Netty 实现 TCP 协议的简单应用。 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它为两台计算机之间的数据传输提供了有序、无损...

    netty http协议开发小例子

    在本文中,我们将深入探讨如何使用 Netty 实现 HTTP 协议的开发,结合提供的“NettyStudyServer”文件,我们来详细了解一下相关知识点。 1. **HTTP 协议基础** - HTTP(超文本传输协议)是互联网上应用最为广泛的...

    Netty学习笔记_Springboot实现自定义协议.docx

    在本文中,我们将使用Springboot框架来实现一个简单的服务端和客户端程序,并使用Netty框架来处理网络通信。 首先,我们需要添加Netty依赖项到我们的Springboot项目中。我们可以在pom.xml文件中添加以下依赖项: `...

    netty做服务端支持ssl协议实现websocket的wss协议(java)

    在这个场景中,我们关注的是如何使用Netty来实现服务端支持SSL协议,以便实现WebSocket的WSS(Secure WebSocket)协议。WSS是WebSocket的加密版本,它通过SSL/TLS提供安全的通信,类似于HTTPS对于HTTP的关系。 首先...

    netty的rpc协议的简单实现

    在这个“netty的rpc协议的简单实现”项目中,我们将探讨Netty如何被用来构建RPC框架的关键组件和流程。 首先,我们需要理解RPC的基本原理。RPC的核心是封装网络通信细节,使得客户端和服务器之间通过接口进行通信,...

    netty5 HTTP协议栈浅析与实践

    在本文中,我们将深入浅出地探讨 Netty 实现的 HTTP 协议栈,并通过实践来理解其工作原理。 首先,我们要了解 HTTP 协议的基本概念。HTTP(超文本传输协议)是互联网上应用最广泛的一种网络协议,它定义了客户端和...

    netty http client & server

    而在 "netty-http-client" 文件中,包含了一个简单的 HTTP 客户端示例,演示了如何向服务器发送请求并接收响应。 总的来说,Netty 提供了强大而灵活的工具来构建 HTTP 客户端和服务器,无论是对于学习网络编程,...

    Netty权威指南--私有协议栈功能实现

    总的来说,Netty 提供了丰富的工具和接口,使得构建私有协议栈变得简单而高效。通过自定义 ChannelHandler,你可以实现编解码、权限验证和心跳包等各种复杂功能。在实践中,不断优化和调试你的代码,以确保其性能和...

    基于java GUI界面的简易netty聊天室(实现群聊和私聊)

    【标题】基于Java GUI界面的简易Netty聊天室实现了群聊和私聊功能,通过集成FastJSON库处理JSON格式的数据编码与解码。这个项目旨在为用户提供一个简单易用的聊天平台,用户可以通过图形化界面进行实时通信。下面将...

    netty实现简单的聊天

    在这个“netty实现简单的聊天”的项目中,我们主要关注的是如何利用Netty构建一个基本的聊天系统,这涉及到网络通信、连接管理、消息编码与解码以及错误处理等多个关键知识点。 首先,我们要理解Netty的五大组件:...

    netty实现的聊天代码

    在这个“netty实现的聊天代码”中,我们可以深入理解如何使用 Netty 框架来构建简单的聊天应用。这个 demo 包括了 server 和 client 两部分,都是基于 Java 语言编写的,因此也涉及到了 Java 编程。 首先,让我们从...

    websocket netty实现的简单聊天系统

    在这个基于WebSocket和Netty实现的简单聊天系统中,我们可以深入探讨这两个技术的应用及其背后的原理。 WebSocket是一种在客户端和服务器之间建立长时间连接的协议,允许双向通信。传统的HTTP协议在每次请求-响应...

    netty http protobuf

    Netty、HTTP与Protobuf是三个在IT领域中至关重要的技术组件,它们分别在不同的层面上为高...通过Netty实现HTTP服务器和客户端,利用Protobuf进行高效的数据序列化和反序列化,可以极大地提升应用程序的性能和可扩展性。

    springboot+netty 实现简单的一对一聊天

    在本文中,我们将深入探讨如何使用Spring Boot和Netty实现一个简单的一对一聊天应用程序。Spring Boot是Java领域中广泛使用的微服务框架,它简化了配置并提供了快速启动的应用程序开发体验。Netty则是一个高性能、...

    整合netty实时通讯

    Netty 提供了对 WebSocket 协议的全面支持,使得开发者可以轻松实现 WebSocket 服务器和客户端。 1. **Netty 框架简介** - Netty 的核心是它的事件驱动模型,基于 NIO(非阻塞 I/O)和 Channel 体系结构。这个模型...

    使用 netty实现一个简单的聊天室

    在这个“使用 Netty 实现一个简单的聊天室”的项目中,我们将深入理解 Netty 的核心概念和组件,以及如何利用它们构建一个实时交互的聊天应用。 1. **Netty 基本概念** - **BossGroup 和 WorkerGroup**:在 Netty ...

    Netty实现简单的客户端服务端通信示例

    在本文中,我们将深入探讨如何使用 Netty 实现简单的客户端-服务端通信,这对于初学者来说是一个很好的起点。 首先,理解 Netty 的核心概念至关重要。Netty 的设计基于 NIO(非阻塞 I/O),它利用了 Java 提供的 ...

    一个基于Nacos、Netty、Protobuf 实现的简单易懂的RCP框架.zip

    标题中的“一个基于Nacos、Netty、Protobuf 实现的简单易懂的RCP框架”指的是一个使用了阿里巴巴的Nacos服务发现平台、高性能的网络库Netty以及高效的序列化协议Protobuf来构建的远程过程调用(RPC)框架。...

    Netty实现简单的聊天消息群发功能

    本项目通过Netty实现了一个简单的聊天消息群发功能,使得多个客户端可以向服务端发送消息,服务端接收到消息后,再广播给所有连接的客户端。这对于构建分布式聊天系统或者实时通知系统非常有用。 首先,我们要理解...

Global site tag (gtag.js) - Google Analytics