特点: 1.可以在浏览器里使用 2.支持双向通信 3.使用简单 全双工异步通信,tcp协议服用http握手通道 优点: 1.双向通信,实时性更强。 2.更好的二进制支持 3.较少的控制开销。连接创建后,ws客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不包含头部的情况下,服务端到客户端的包头只有2~10字节(取决于数据包长度),客户端到服务端的的话,需要加上额外的4字节的掩码。而HTTP协议每次通信都需要携带完整的头部。 了解知识点: a.建立连接 b.交换数据 c.数据帧格式 d.如何维持连接
支持方式: 1.java端作为服务端 2.另起前端作为服务端
java作为服务端时:
/** * 初始化器: */ public class NettyServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline= socketChannel.pipeline(); //以下三个是Http的支持 //http解码器 pipeline.addLast(new HttpServerCodec()); //支持写大数据流 pipeline.addLast(new ChunkedWriteHandler()); //http聚合器 pipeline.addLast(new HttpObjectAggregator(1024*62)); //websocket支持,设置路由 pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); //添加自定义的助手类 pipeline.addLast(new NettyHandler()); } }
package com.example.demo.netty.nettyprogram; import com.alibaba.fastjson.JSON; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import io.netty.util.concurrent.GlobalEventExecutor; /** * 自定义助手类: * 这个类就是业务的核心,客户端的请求会在这里处理。 * 比如客户端连接、客户端发送消息、给客户端发送消息等等。 * 自定义助手类需要重写的方法可以根据自己的需求重写, * 这里就不把每个方法都重写一遍了,完整的大家可以去找找文档看看。 */ public class NettyHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> { //TextWebSocketFrame是netty用于处理websocket发来的文本对象 //所有正在连接的channel都会存在这里面,所以也可以间接代表在线的客户端 public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); //在线人数 public static int online; //接收到客户都发送的消息 @Override public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { final String text = msg.text();//客户端发送的文本信息,可以根据需要转换成send_message Send_Message send_message=new Send_Message(); SendAllMessages(ctx,send_message);//send_message是我的自定义类型,前后端分离往往需要统一数据格式,可以先把对象转成json字符串再发送给客户端 } //客户端建立连接 @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { channelGroup.add(ctx.channel()); online=channelGroup.size(); System.out.println(ctx.channel().remoteAddress()+"上线了!"); } //关闭连接 @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { channelGroup.remove(ctx.channel()); online=channelGroup.size(); System.out.println(ctx.channel().remoteAddress()+"断开连接"); } //出现异常 @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); } //给某个人发送消息 private void SendMessage(ChannelHandlerContext ctx, Send_Message msg) { ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(msg))); } //给每个人发送消息,除发消息人外 private void SendAllMessages(ChannelHandlerContext ctx,Send_Message msg) { for(Channel channel:channelGroup){ if(!channel.id().asLongText().equals(ctx.channel().id().asLongText())){ channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(msg))); } } } }
public class NettyServer { private static int port; public NettyServer(int port) { this.port = port; } public static void start() throws InterruptedException {//在main方法里调用这个方法,并用构造函数设置端口号 //创建主线程组,接收请求 EventLoopGroup bossGroup = new NioEventLoopGroup(); //创建从线程组,处理主线程组分配下来的io操作 EventLoopGroup workerGroup = new NioEventLoopGroup(); //创建netty服务器 try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup)//设置主从线程组 .channel(NioServerSocketChannel.class)//设置通道 .childHandler(new NettyServerInitializer());//子处理器,用于处理workerGroup中的操作 //启动server ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); //监听关闭channel channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully();//关闭主线程 workerGroup.shutdownGracefully();//关闭从线程 } } }
另起的前端作为服务端:WebSocket服务端 服务端用了ws这个库。相比大家熟悉的socket.io,ws实现更轻量 var app = require('express')(); var server = require('http').Server(app); var WebSocket = require('ws'); var wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', function connection(ws) { console.log('server: receive connection.'); ws.on('message', function incoming(message) { console.log('server: received: %s', message); }); ws.send('world'); }); app.get('/', function (req, res) { res.sendfile(__dirname + '/index.html'); }); app.listen(3000);
客户端:向8080端口发起WebSocket连接。连接建立后,打印日志,同时向服务端发送消息。接收到来自服务端的消息后 <script> var ws = new WebSocket('ws://localhost:8080'); ws.onopen = function () { console.log('ws onopen'); ws.send('from client: hello'); }; ws.onmessage = function (e) { console.log('ws onmessage'); console.log('from server: ' + e.data); }; </script>
标签:websocket,ctx,介绍,ws,new,public,channel,客户端 From: https://www.cnblogs.com/wangbiaohistory/p/17367145.html