Netty学习笔记(六)Springboot实现基于http协议的简单服务器---浏览器和客户端访问
2019-04-03 12:34
916 查看
参考文章: https://www.geek-share.com/detail/2708436881.html
上代码
-
建服务器启动类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的话,是一直一直连接着的,即使你关了浏览器
-
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(); } } }
-
数据处理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; } }
-
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(); } }
——————————————————我是分割线,下面是客户端——————————————————————————
-
启动类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(); } } }
-
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(); } }
-
ByteBufToBytes类,和上面一样的
-
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>
结语
大家可以根据需要添加些进阶功能
相关文章推荐
- 基于HTTP、NIO、单线程实现浏览器并发非阻塞访问服务器文件
- 基于Netty4构建HTTP服务----浏览器访问和Netty客户端访问
- 基于NIO实现客户端通过HTTP协议访问WEB站点
- 基于Spring Boot 2.0 及MongoDB 3.6.2 实现的简单文件共享服务器
- SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建
- spring学习笔记6--简单模拟实现AOP(cglib版)
- 左右互搏,基于http的xml消息的服务器和客户端实现
- memcached学习——常用命令+基于java客户端的3种简单实现(二)
- Python模块学习 ---- httplib HTTP协议客户端实现
- 实现采用客户/服务器通信模式,基于TCP网络通信协议的多客户端简单应用
- 基于Spring Boot和Spring Cloud实现微服务架构学习(四)-Spring Cloud总结
- 基于Java实现简单Http服务器之一
- 基于RFC6265 (HTTP状态管理协议)实现简单的登录系统
- 基于Spring Boot和Spring Cloud实现微服务架构学习(六)-Docker应用
- asio学习笔记-简单的http客户端
- (3)Spring-boot学习 做一个简单的带访问数据库的web项目
- 基于Spring Boot和Spring Cloud实现微服务架构学习
- 基于Java实现简单Http服务器之一
- 利用socket自己实现基于HTTP协议的Web服务器
- Node.js学习笔记(4)——除了HTTP(服务器和客户端)部分