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 协议的简单应用。 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它为两台计算机之间的数据传输提供了有序、无损...
在本文中,我们将深入探讨如何使用 Netty 实现 HTTP 协议的开发,结合提供的“NettyStudyServer”文件,我们来详细了解一下相关知识点。 1. **HTTP 协议基础** - HTTP(超文本传输协议)是互联网上应用最为广泛的...
在本文中,我们将使用Springboot框架来实现一个简单的服务端和客户端程序,并使用Netty框架来处理网络通信。 首先,我们需要添加Netty依赖项到我们的Springboot项目中。我们可以在pom.xml文件中添加以下依赖项: `...
在这个场景中,我们关注的是如何使用Netty来实现服务端支持SSL协议,以便实现WebSocket的WSS(Secure WebSocket)协议。WSS是WebSocket的加密版本,它通过SSL/TLS提供安全的通信,类似于HTTPS对于HTTP的关系。 首先...
在这个“netty的rpc协议的简单实现”项目中,我们将探讨Netty如何被用来构建RPC框架的关键组件和流程。 首先,我们需要理解RPC的基本原理。RPC的核心是封装网络通信细节,使得客户端和服务器之间通过接口进行通信,...
在本文中,我们将深入浅出地探讨 Netty 实现的 HTTP 协议栈,并通过实践来理解其工作原理。 首先,我们要了解 HTTP 协议的基本概念。HTTP(超文本传输协议)是互联网上应用最广泛的一种网络协议,它定义了客户端和...
而在 "netty-http-client" 文件中,包含了一个简单的 HTTP 客户端示例,演示了如何向服务器发送请求并接收响应。 总的来说,Netty 提供了强大而灵活的工具来构建 HTTP 客户端和服务器,无论是对于学习网络编程,...
总的来说,Netty 提供了丰富的工具和接口,使得构建私有协议栈变得简单而高效。通过自定义 ChannelHandler,你可以实现编解码、权限验证和心跳包等各种复杂功能。在实践中,不断优化和调试你的代码,以确保其性能和...
【标题】基于Java GUI界面的简易Netty聊天室实现了群聊和私聊功能,通过集成FastJSON库处理JSON格式的数据编码与解码。这个项目旨在为用户提供一个简单易用的聊天平台,用户可以通过图形化界面进行实时通信。下面将...
在这个“netty实现简单的聊天”的项目中,我们主要关注的是如何利用Netty构建一个基本的聊天系统,这涉及到网络通信、连接管理、消息编码与解码以及错误处理等多个关键知识点。 首先,我们要理解Netty的五大组件:...
在这个“netty实现的聊天代码”中,我们可以深入理解如何使用 Netty 框架来构建简单的聊天应用。这个 demo 包括了 server 和 client 两部分,都是基于 Java 语言编写的,因此也涉及到了 Java 编程。 首先,让我们从...
在这个基于WebSocket和Netty实现的简单聊天系统中,我们可以深入探讨这两个技术的应用及其背后的原理。 WebSocket是一种在客户端和服务器之间建立长时间连接的协议,允许双向通信。传统的HTTP协议在每次请求-响应...
Netty、HTTP与Protobuf是三个在IT领域中至关重要的技术组件,它们分别在不同的层面上为高...通过Netty实现HTTP服务器和客户端,利用Protobuf进行高效的数据序列化和反序列化,可以极大地提升应用程序的性能和可扩展性。
在本文中,我们将深入探讨如何使用Spring Boot和Netty实现一个简单的一对一聊天应用程序。Spring Boot是Java领域中广泛使用的微服务框架,它简化了配置并提供了快速启动的应用程序开发体验。Netty则是一个高性能、...
Netty 提供了对 WebSocket 协议的全面支持,使得开发者可以轻松实现 WebSocket 服务器和客户端。 1. **Netty 框架简介** - Netty 的核心是它的事件驱动模型,基于 NIO(非阻塞 I/O)和 Channel 体系结构。这个模型...
在这个“使用 Netty 实现一个简单的聊天室”的项目中,我们将深入理解 Netty 的核心概念和组件,以及如何利用它们构建一个实时交互的聊天应用。 1. **Netty 基本概念** - **BossGroup 和 WorkerGroup**:在 Netty ...
在本文中,我们将深入探讨如何使用 Netty 实现简单的客户端-服务端通信,这对于初学者来说是一个很好的起点。 首先,理解 Netty 的核心概念至关重要。Netty 的设计基于 NIO(非阻塞 I/O),它利用了 Java 提供的 ...
标题中的“一个基于Nacos、Netty、Protobuf 实现的简单易懂的RCP框架”指的是一个使用了阿里巴巴的Nacos服务发现平台、高性能的网络库Netty以及高效的序列化协议Protobuf来构建的远程过程调用(RPC)框架。...
本项目通过Netty实现了一个简单的聊天消息群发功能,使得多个客户端可以向服务端发送消息,服务端接收到消息后,再广播给所有连接的客户端。这对于构建分布式聊天系统或者实时通知系统非常有用。 首先,我们要理解...