使用Netty做WebSocket服务端

  使用Netty搭建WebSocket服务器

1.WebSocketServer.java

public class WebSocketServer {
    private final ChannelGroup group = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);

    private final EventLoopGroup workerGroup = new NioEventLoopGroup();

    private Channel channel;

    public ChannelFuture start(InetSocketAddress address) {
        ServerBootstrap boot = new ServerBootstrap();
        boot.group(workerGroup).channel(NioServerSocketChannel.class).childHandler(createInitializer(group));

        ChannelFuture f = boot.bind(address).syncUninterruptibly();
        channel = f.channel();
        return f;
    }

    protected ChannelHandler createInitializer(ChannelGroup group2) {
        return new ChatServerInitializer(group2);
    }

    public void destroy() {
        if (channel != null)
            channel.close();
        group.close();
        workerGroup.shutdownGracefully();
    }

    public static void main(String[] args) {
        final WebSocketServer server = new WebSocketServer();
        ChannelFuture f = server.start(new InetSocketAddress(2048));
        System.out.println("server start................");
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                server.destroy();
            }
        });
        f.channel().closeFuture().syncUninterruptibly();
    }

    private static WebSocketServer instance;

    private WebSocketServer() {}

    public static synchronized WebSocketServer getInstance() {// 懒汉,线程安全
        if (instance == null) {
            instance = new WebSocketServer();
        }
        return instance;
    }

    public void running(){
        if(instance != null){

            String port=null;
            port=BusinessConfigUtils.findProperty("websocket_port");//获取端口号
            if(null==port||port.length()<0||!StringUtils.isNumeric(port)){
                port="18080";
            }
            instance.start(new InetSocketAddress(Integer.valueOf(port)));
            //ChannelFuture f =
            System.out.println("----------------------------------------WEBSOCKET SERVER START----------------------------------------");
            /*Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    instance.destroy();
                }
            });
            f.channel().closeFuture().syncUninterruptibly();*/
        }
    }
}

2.ChatServerInitializer.java

public class ChatServerInitializer extends ChannelInitializer<Channel> {

	private final ChannelGroup group;
	public ChatServerInitializer(ChannelGroup group) {
		super();
		this.group = group;
	}

	@Override
	protected void initChannel(Channel ch) throws Exception {
		ChannelPipeline pipeline = ch.pipeline();

		pipeline.addLast(new HttpServerCodec());

		pipeline.addLast(new ChunkedWriteHandler());

		pipeline.addLast(new HttpObjectAggregator(64*1024));

		pipeline.addLast(new HttpRequestHandler("/ws"));

		pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));

		pipeline.addLast(new TextWebSocketFrameHandler(group));

	}

}

 3. HttpRequestHandler.java

public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

	private LoginTimeService loginTimeService = SpringContextHolder.getBean("loginTimeServiceImpl");
	private final String wsUri;

	public HttpRequestHandler(String wsUri) {
		super();
		this.wsUri = wsUri;
	}

	@Override
	@SuppressWarnings("deprecation")
	protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
		if (wsUri.equalsIgnoreCase(msg.getUri().substring(0, 3))) {
			String userId = findUserIdByUri(msg.getUri());
			if (userId != null && userId.trim() != null && userId.trim().length() > 0) {
				ctx.channel().attr(AttributeKey.valueOf(ctx.channel().id().asShortText())).set(userId);// 写userid值
				UserIdToWebSocketChannelShare.userIdToWebSocketChannelMap.put(userId, ctx.channel()); // 用户Id与Channel绑定
				loginTimeService.onLine(userId, new Date());// 统计上线记录

			} else {
			}// 没有获取到用户Id
			ctx.fireChannelRead(msg.setUri(wsUri).retain());
		}
	}

	private String findUserIdByUri(String uri) {// 通过Uid获取用户Id--uri中包含userId
		String userId = "";
		try {
			userId = uri.substring(uri.indexOf("userId") + 7);
			if (userId != null && userId.trim() != null && userId.trim().length() > 0) {
				userId = userId.trim();
			}
		} catch (Exception e) {
		}
		return userId;
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		ctx.close();
		cause.printStackTrace(System.err);
	}
}

 4. TextWebSocketFrameHandler.java

public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

	private LoginTimeService loginTimeService = SpringContextHolder.getBean("loginTimeServiceImpl");
	private final ChannelGroup group;

	public TextWebSocketFrameHandler(ChannelGroup group) {
		super();
		this.group = group;
	}

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		if (evt == WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE) {
			ctx.pipeline().remove(HttpRequestHandler.class);
			// group.writeAndFlush("");
			group.add(ctx.channel());
		} else {
			super.userEventTriggered(ctx, evt);
		}
	}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
		group.writeAndFlush(msg.retain());
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		ctx.close();
		cause.printStackTrace();
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception { // (6)
		Channel incoming = ctx.channel();
		String userId = (String) incoming.attr(AttributeKey.valueOf(incoming.id().asShortText())).get();
		UserIdToWebSocketChannelShare.userIdToWebSocketChannelMap.remove(userId);// 删除缓存的通道
		loginTimeService.outLine(userId, new Date());// 下线通过
	}

}

  

时间: 2024-10-11 00:09:53

使用Netty做WebSocket服务端的相关文章

C# WebSocket 服务端示例代码 + HTML5客户端示例代码

WebSocket服务端 C#示例代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Net; using System.Threading; using System.Text.RegularExpressions; using System.Security.Cryptography; na

用nodejs快速实现websocket服务端(带SSL证书生成)

有不少公司将nodejs的socket.io作为websocket的解决方案,很遗憾的是socket.io是对websocket的封装,并不支持html5原始的websocket协议,微信小程序使用的websocket却是接近于html5原始websocket协议,socket.io居然没有用武之地了. 当然情况也没有惨到需要你自己一步一步去实现websocket服务端,我们的大node有很多websocket库,ws就是其中一个,号称最轻量级,最快.ws的用法比较简单,直接看github说明(

.NET 即时通信,WebSocket服务端实例

即时通信常用手段 1.第三方平台 谷歌.腾讯 环信等多如牛毛,其中谷歌即时通信是免费的,但免费就是免费的并不好用.其他的一些第三方一般收费的,使用要则限流(1s/限制x条消息)要么则限制用户数. 但稳定性什么都还不错,又能将服务压力甩出 2.System.Net.Sockets.Socket,也能写一套较好的服务器端.在.NET 4.5之前用较多,使用起来麻烦.需要对数据包进行解析等操作(但貌似网上有对超长包的处理方法) 3.System.Net.WebSockets.WebSocket,这个,

websocket服务端开发

基于http请求以拉的方式去做服务器的推送,无论是实时性和有效字节都是差强人意的效果. 公司的im系统在与客户端的交互上实际上借助了websocket来实现服务器与客户端的事实消息推送,今天就来简单了解下这个协议,并且自己实现对websocket的响应. 可以看到在理解了tcp和http之后,websocket的设计其实并不复杂,再最开始建立链接的时候客户端实际上会进行一次http请求,只不过请求头的内容有些特别,这里我们来看下: GET /chat HTTP/1.1 Host: server.

Pywss - 用python实现WebSocket服务端

一种类似Flask开发的WebSocket-Server服务端框架,适用python3.X 1.安装模块Pywss pip install pywss 2.搭建简易服务器 2.1 服务端代码 代码简介 route: 注册请求路径 example_1(request, data): request: socket句柄,能够发送和接收数据接.发送数据request.ws.send(data),收数据request.ws_recv(1024) data: 客户端发送的数据存于此处 from pywss

[Go] 实现websocket服务端

直接使用官方子包可以实现websocket协议, golang.org/x/net/websocket 如果在这个目录没有这个包就去github下载net库,放进这个目录$GOPATH/src/golang.org/x/net就行了 服务端代码: package main import ( "time" "log" "net/http" "golang.org/x/net/websocket" ) func main(){ h

用java做thrift服务端,php做thrift客户端简单例子

注意: 1).需要的包以及路径问题要注意修改为自己本地的 2)详细情况见  http://pan.baidu.com/s/1qW8xI0k 这里以Hello.thrift为例 namespace java hellodemo namespace php hellodemo service Hello{ string helloString(1:string para) i32 helloInt(1:i32 para) bool helloBoolean(1:bool para) void hel

WebSocket服务端和客户端使用

using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net;using System.Net.WebSockets;using System.Text;using System.Threading;using System.Threading.Tasks;using WindowsServiceTest; namespace WindowsService{ ///

一步一步学WebSocket(二) 使用SuperWebSocket实现自己的服务端

上一篇文章,我们了解了客户端如何与服务器创建WebSocket连接.但是一个巴掌拍不响,既然是通信,就必然最少要有两个端.今天我们来看看c#如何用已有的框架实现一个WebSocket服务端. 在.Net Framework 4.5及以上版本中,微软为我们集成了WebSocket协议的基本实现.微软提供的WebSocket对象位于System.Net.WebSocket命名空间下,使用起来挺繁琐的,所以我选择了SuperWebSocket框架来简化开发的难度. SuperWebSocket框架可以