websocket时h5时期提供的在单个TCP链接上进行全双工的通讯协议,使客户端和服务器端能够实时通信
public class ServerMain {
public static void main(String[] args) throws Exception{
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup wokerGroup = new NioEventLoopGroup();
try{
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,wokerGroup).channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.option(ChannelOption.SO_KEEPALIVE,true)
.option(ChannelOption.SO_BACKLOG,1024*1024*10)
.childHandler(new WebSocketChannelInitializer());
ChannelFuture channelFuture = serverBootstrap.bind(new InetSocketAddress(8899)).sync();
channelFuture.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
wokerGroup.shutdownGracefully();
}
}
}
server端用发和平时一样,1.先创建一个bossGroup 用来处理连接 2创建一个wokerGroup用来处理后续事件,3.创建ServerBootstrap 设置熟悉,添加ChannelInitializer 4.启动监听8899端口
public class WebSocketChannelInitializer extends ChannelInitializer {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//websocket协议本身是基于http协议的,所以这边也要使用http解编码器
pipeline.addLast(new HttpServerCodec());
//以块的方式来写的处理器
pipeline.addLast(new ChunkedWriteHandler());
//netty是基于分段请求的,HttpObjectAggregator的作用是将请求分段再聚合,参数是聚合字节的最大长度
pipeline.addLast(new HttpObjectAggregator(1024*1024*1024));
//ws://server:port/context_path
//ws://localhost:9999/ws
//参数指的是contex_path
pipeline.addLast(new WebSocketServerProtocolHandler("/ws",null,true,65535));
//websocket定义了传递数据的6中frame类型
pipeline.addLast(new WebSocketHandle());
}
}
public class WebSocketHandle extends SimpleChannelInboundHandler
WebSocketHandle 是真正处理业务请求的
###基于netty 的websocket client 端
public class ClientMain {
public static void main(String[] args) throws Exception{
EventLoopGroup group=new NioEventLoopGroup();
Bootstrap boot=new Bootstrap();
boot.option(ChannelOption.SO_KEEPALIVE,true)
.option(ChannelOption.TCP_NODELAY,true)
.group(group)
.handler(new LoggingHandler(LogLevel.INFO))
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline p = socketChannel.pipeline();
p.addLast(new ChannelHandler[]{new HttpClientCodec(),
new HttpObjectAggregator(1024*1024*10)});
p.addLast("hookedHandler", new WebSocketClientHandler());
}
});
URI websocketURI = new URI("ws://localhost:8899/ws");
HttpHeaders httpHeaders = new DefaultHttpHeaders();
//进行握手
WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(websocketURI, WebSocketVersion.V13, (String)null, true,httpHeaders);
System.out.println("connect");
final Channel channel=boot.connect(websocketURI.getHost(),websocketURI.getPort()).sync().channel();
WebSocketClientHandler handler = (WebSocketClientHandler)channel.pipeline().get("hookedHandler");
handler.setHandshaker(handshaker);
handshaker.handshake(channel);
//阻塞等待是否握手成功
handler.handshakeFuture().sync();
Thread text=new Thread(new Runnable() {
public void run() {
int i=30;
while (i>0){
System.out.println("text send");
TextWebSocketFrame frame = new TextWebSocketFrame("我是文本");
channel.writeAndFlush(frame).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if(channelFuture.isSuccess()){
System.out.println("text send success");
}else{
System.out.println("text send failed "+channelFuture.cause().getMessage());
}
}
});
}
}
});
Thread bina=new Thread(new Runnable() {
public void run() {
File file=new File("C:\\Users\\Administrator\\Desktop\\test.wav");
FileInputStream fin= null;
try {
fin = new FileInputStream(file);
int len=0;
byte[] data=new byte[1024];
while ((len=fin.read(data))>0){
ByteBuf bf=Unpooled.buffer().writeBytes(data);
BinaryWebSocketFrame binaryWebSocketFrame=new BinaryWebSocketFrame(bf);
channel.writeAndFlush(binaryWebSocketFrame).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if(channelFuture.isSuccess()){
System.out.println("bina send success");
}else{
System.out.println("bina send failed "+channelFuture.cause().toString());
}
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
text.start();
bina.start();
}
}
这边我开启了两个线程发送不同的帧数据,注意点1.在连接后需要通过
WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(websocketURI, WebSocketVersion.V13, (String)null, true,httpHeaders);
创建握手协议,在Handler中处理握手协议的返回,client在阻塞等待是否握手成功
注意点2:client发送的数据一定不能大于握手协议中规定的帧的最大长度
public class WebSocketClientHandler extends SimpleChannelInboundHandler
完毕