Netty案例介绍(websocket服务)

channelHandlerContext.writeAndFlush(new TextWebSocketFrame("服务器时间: " + LocalDateTime.now() + " : " + textWebSocketFrame.text()));

}

/**

  • 客户端连接的时候触发

  • @param ctx

  • @throws Exception

*/

@Override

public void handlerAdded(ChannelHandlerContext ctx) throws Exception {

// LongText() 唯一的 ShortText() 不唯一

System.out.println(“handlerAdded:” + ctx.channel().id().asLongText());

System.out.println(“handlerAdded:” + ctx.channel().id().asShortText());

}

/**

  • 客户端断开连接的时候触发

  • @param ctx

  • @throws Exception

*/

@Override

public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {

System.out.println(“handlerRemoved:” + ctx.channel().id().asLongText());

}

@Override

public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

System.out.println(“异常发生了…”);

ctx.close();

}

}

2.2 服务端

服务端代码在原有的基础上需要转换相关的协议,具体如下:

package com.dpb.netty.websocket;

import io.netty.bootstrap.ServerBootstrap;

import io.netty.channel.*;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.ServerSocketChannel;

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.HttpServerCodec;

import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;

import io.netty.handler.logging.LogLevel;

import io.netty.handler.logging.LoggingHandler;

import io.netty.handler.stream.ChunkedWriteHandler;

import java.net.ServerSocket;

/**

  • @program: netty4demo

  • @description: 基于WebSocket协议的服务端

  • @author: 波波烤鸭

  • @create: 2019-12-30 22:31

*/

public class SocketServerDemo {

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

// 1.创建对应的EventLoopGroup对象

EventLoopGroup bossGroup = new NioEventLoopGroup(1);

EventLoopGroup workGroup = new NioEventLoopGroup();

ServerBootstrap bootstrap = new ServerBootstrap();

try{

bootstrap.group(bossGroup,workGroup)

.channel(NioServerSocketChannel.class)

.handler(new LoggingHandler(LogLevel.INFO))

.childHandler(new ChannelInitializer() {

@Override

protected void initChannel(SocketChannel socketChannel) throws Exception {

// websocket 相关的配置

ChannelPipeline pipeline = socketChannel.pipeline();

//因为基于http协议,使用http的编码和解码器

pipeline.addLast(new HttpServerCodec());

//是以块方式写,添加ChunkedWriteHandler处理器

pipeline.addLast(new ChunkedWriteHandler());

/*

说明

  1. http数据在传输过程中是分段, HttpObjectAggregator ,就是可以将多个段聚合

  2. 这就就是为什么,当浏览器发送大量数据时,就会发出多次http请求

*/

pipeline.addLast(new HttpObjectAggregator(8192));

/*

说明

  1. 对应websocket ,它的数据是以 帧(frame) 形式传递

  2. 可以看到WebSocketFrame 下面有六个子类

  3. 浏览器请求时 ws://localhost:8888/hello 表示请求的uri

  4. WebSocketServerProtocolHandler 核心功能是将 http协议升级为 ws协议 , 保持长连接

  5. 是通过一个 状态码 101

*/

pipeline.addLast(new WebSocketServerProtocolHandler(“/hello”));

// 自定义handler,处理业务逻辑

pipeline.addLast(new SocketServerHandler());

}

});

System.out.println(“服务启动了…”);

ChannelFuture future = bootstrap.bind(8888).sync();

future.channel().closeFuture().sync();

}finally {

bossGroup.shutdownGracefully();

workGroup.shutdownGracefully();

}

}

}

2.3 客户端实现

在客户端中我们就简单的实现一个HTML页面,在其中发送websocket协议相关的请求,然后接受相关的消息,如下,注意注释

websocket案例测试
以下是一个简单的Netty实现WebSocket协议的服务端和客户端案例服务端代码: ```java 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.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; public class WebSocketServer { private final int port; public WebSocketServer(int port) { this.port = port; } public void start() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap() .group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpObjectAggregator(65536)); pipeline.addLast(new WebSocketServerProtocolHandler("/websocket")); pipeline.addLast(new WebSocketServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture future = bootstrap.bind(port).sync(); System.out.println("WebSocket Server started on port " + port); future.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { new WebSocketServer(8080).start(); } } ``` 客户端代码: ```java import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; 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.*; import io.netty.handler.codec.http.websocketx.*; import io.netty.util.CharsetUtil; import java.net.URI; public class WebSocketClient { private final URI uri; private final WebSocketClientHandler handler = new WebSocketClientHandler(); private Channel channel; public WebSocketClient(URI uri) { this.uri = uri; } public void start() throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap() .group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new HttpClientCodec()); pipeline.addLast(new HttpObjectAggregator(8192)); pipeline.addLast(new WebSocketClientProtocolHandler(uri, WebSocketVersion.V13, null, true, HttpHeaders.EMPTY_HEADERS, 65536)); pipeline.addLast(handler); } }); channel = bootstrap.connect(uri.getHost(), uri.getPort()).sync().channel(); handler.handshakeFuture().sync(); System.out.println("WebSocket Client connected to " + uri); } catch (Exception e) { group.shutdownGracefully(); } } public void stop() { channel.writeAndFlush(new CloseWebSocketFrame()); try { channel.closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } } public void sendMessage(String message) { channel.writeAndFlush(new TextWebSocketFrame(message)); } public static void main(String[] args) throws Exception { WebSocketClient client = new WebSocketClient(new URI("ws://localhost:8080/websocket")); client.start(); client.sendMessage("Hello, Netty WebSocket!"); Thread.sleep(1000); client.stop(); } private static class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> { private final WebSocketClientHandshaker handshaker; private ChannelPromise handshakeFuture; public WebSocketClientHandler() { URI uri = URI.create("ws://localhost:8080/websocket"); handshaker = WebSocketClientHandshakerFactory.newHandshaker(uri, WebSocketVersion.V13, null, true, HttpHeaders.EMPTY_HEADERS, 65536); } public ChannelFuture handshakeFuture() { return handshakeFuture; } @Override public void handlerAdded(ChannelHandlerContext ctx) { handshakeFuture = ctx.newPromise(); } @Override public void channelActive(ChannelHandlerContext ctx) { handshaker.handshake(ctx.channel()); } @Override public void channelInactive(ChannelHandlerContext ctx) { System.out.println("WebSocket Client disconnected!"); } @Override public void channelRead0(ChannelHandlerContext ctx, Object msg) { Channel ch = ctx.channel(); if (!handshaker.isHandshakeComplete()) { handshaker.finishHandshake(ch, (FullHttpResponse) msg); System.out.println("WebSocket Client connected!"); handshakeFuture.setSuccess(); return; } if (msg instanceof FullHttpResponse) { FullHttpResponse response = (FullHttpResponse) msg; throw new IllegalStateException( "Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content().toString(CharsetUtil.UTF_8) + ')'); } WebSocketFrame frame = (WebSocketFrame) msg; if (frame instanceof TextWebSocketFrame) { TextWebSocketFrame textFrame = (TextWebSocketFrame) frame; System.out.println("WebSocket Client received message: " + textFrame.text()); } else if (frame instanceof PongWebSocketFrame) { System.out.println("WebSocket Client received pong"); } else if (frame instanceof CloseWebSocketFrame) { System.out.println("WebSocket Client received closing"); ch.close(); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); if (!handshakeFuture.isDone()) { handshakeFuture.setFailure(cause); } ctx.close(); } } } ``` 使用时,先启动服务端,再启动客户端。客户端启动后,会向服务端发送一条消息,并在接收到服务端的响应后关闭连接。在控制台上可以看到客户端和服务端的交互过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值