Netty实现长连接简单例子

来源:互联网 发布:微信转换淘宝链接 编辑:程序博客网 时间:2024/05/22 06:06

Netty实现长连接的简单例子

服务端

NettyServerBootstrap提供长连接服务

public class NettyServerBootstrap {private static final Log log = LogFactory.getLog(NettyServerBootstrap.class);private Integer port;private SocketChannel socketChannel;public NettyServerBootstrap(Integer port) throws Exception {this.port = port;bind(port);}public Integer getPort() {return port;}public void setPort(Integer port) {this.port = port;}public SocketChannel getSocketChannel() {return socketChannel;}public void setSocketChannel(SocketChannel socketChannel) {this.socketChannel = socketChannel;}private void bind(int serverPort) throws Exception {// 连接处理groupEventLoopGroup boss = new NioEventLoopGroup();// 事件处理groupEventLoopGroup worker = new NioEventLoopGroup();ServerBootstrap bootstrap = new ServerBootstrap();// 绑定处理groupbootstrap.group(boss, worker);bootstrap.channel(NioServerSocketChannel.class);// 保持连接数bootstrap.option(ChannelOption.SO_BACKLOG, 1024 * 1024);// 有数据立即发送bootstrap.option(ChannelOption.TCP_NODELAY, true);// 保持连接bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);       // 处理新连接bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel sc) throws Exception {// 增加任务处理ChannelPipeline p = sc.pipeline();p.addLast(new MessageDecoder(), new MessageEncoder(), new NettyServerHandler()); }});ChannelFuture f = bootstrap.bind(serverPort).sync();if (f.isSuccess()) {log.info("long connection started success");} else {log.error("long connection started fail");}}}

启动服务,监听9999端口

public static void main(String[] args) {try {new NettyServerBootstrap(9999);} catch (Exception e) {e.printStackTrace();}}

定义客户端服务端通信协议,一下是一个简单的通信协议

协议分为headerbody两部分,都是用网络字节序(BIG ENDIAN

header{

magic 32bit;  //校验用固定值0x0CAFFEE0

version 8bit;  //版本号

type 8bit;     //类型,请求或者响应

seq 32bit;     //序号标记一对请求响应

length 32bit;  //body长度

}

body{

 

}

根据通信协议,编写解码器和编码器

解码器MessageDecoder

public class MessageDecoder extends ByteToMessageDecoder {private static final int MAGIC_NUMBER = 0x0CAFFEE0;public MessageDecoder() {}@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {if (in.readableBytes() < 14) {return;}// 标记开始读取位置in.markReaderIndex();int magic_number = in.readInt();if (MAGIC_NUMBER != magic_number) {ctx.close();return;}@SuppressWarnings("unused")byte version = in.readByte();byte type = in.readByte();int squence = in.readInt();int length = in.readInt();if (length < 0) {ctx.close();return;}if (in.readableBytes() < length) {// 重置到开始读取位置in.resetReaderIndex();return;}byte[] body = new byte[length];in.readBytes(body);RequestInfoVO req = new RequestInfoVO();req.setBody(new String(body, "utf-8"));req.setType(type);req.setSequence(squence);out.add(req);}}

编码器MessageEncoder

public class MessageEncoder extends MessageToByteEncoder<RequestInfoVO> {private static final String DEFAULT_ENCODE = "utf-8";private static final int MAGIC_NUMBER = 0x0CAFFEE0;public MessageEncoder() {}@Overrideprotected void encode(ChannelHandlerContext ctx, RequestInfoVO msg, ByteBuf out) throws Exception {@SuppressWarnings("resource")ByteBufOutputStream writer = new ByteBufOutputStream(out);byte[] body = null;if (null != msg && null != msg.getBody() && "" != msg.getBody()) {body = msg.getBody().getBytes(DEFAULT_ENCODE);}writer.writeInt(MAGIC_NUMBER);writer.writeByte(1);writer.writeByte(msg.getType());writer.writeInt(msg.getSequence());if (null == body || 0 == body.length) {writer.writeInt(0);} else {writer.writeInt(body.length);writer.write(body);}}}

服务端事件处理NettyServerHandler

@Sharablepublic class NettyServerHandler extends SimpleChannelInboundHandler<RequestInfoVO> {private static final Log log = LogFactory.getLog(NettyServerHandler.class);@Overrideprotected void channelRead0(ChannelHandlerContext ctx, RequestInfoVO msg) throws Exception {//}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {}@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {}@Overridepublic void channelUnregistered(ChannelHandlerContext ctx) throws Exception {}}

客户端

NettyClientBootstrap连接长连接服务

public class NettyClientBootstrap {private int port;private String host;private SocketChannel socketChannel;public NettyClientBootstrap(int port, String host) throws Exception {this.host = host;this.port = port;start();}private void start() throws Exception {EventLoopGroup eventLoopGroup = new NioEventLoopGroup();Bootstrap bootstrap = new Bootstrap();bootstrap.channel(NioSocketChannel.class);bootstrap.option(ChannelOption.SO_KEEPALIVE, true);bootstrap.option(ChannelOption.TCP_NODELAY, true);bootstrap.group(eventLoopGroup);bootstrap.remoteAddress(this.host, this.port);bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new MessageDecoder(), new MessageEncoder(), new NettyClientHandler());}});ChannelFuture future = bootstrap.connect(this.host, this.port).sync();if (future.isSuccess()) {socketChannel = (SocketChannel) future.channel();System.out.println("connect server  success|");}}public int getPort() {return this.port;}public void setPort(int port) {this.port = port;}public SocketChannel getSocketChannel() {return socketChannel;}public void setSocketChannel(SocketChannel socketChannel) {this.socketChannel = socketChannel;}public String getHost() {return host;}public void setHost(String host) {this.host = host;}}

初始化客户端

public static void main(String[] args) throws Exception {NettyClientBootstrap bootstrap = new NettyClientBootstrap(9999, "127.0.0.1");int i = 1;while (true) {TimeUnit.SECONDS.sleep(2);RequestInfoVO req = new RequestInfoVO();req.setSequence(123456);req.setType((byte) 1);req.setSequence(0);req.setBody(String.valueOf((new Date()).getTime()));bootstrap.getSocketChannel().writeAndFlush(req);i++;}}

根据协议编写编码器,解码器,同服务端编码器、解码器

客户端事件处理

public class NettyClientHandler extends SimpleChannelInboundHandler<RequestInfoVO> {@Overrideprotected void messageReceived(ChannelHandlerContext ctx, RequestInfoVO msg) throws Exception {System.out.println(msg.getBody());RequestInfoVO req = new RequestInfoVO();req.setSequence(msg.getSequence());req.setType(msg.getType());if (2 == msg.getType()) {req.setBody("client");ctx.channel().writeAndFlush(req);} else if (3 == msg.getType()) {req.setBody("zpksb");ctx.channel().writeAndFlush(req);}}}


至此,实现了简单的客户端服务端长连接。







原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 在微信里面被做微商的骗了钱怎么办 在qq上骗了人50怎么办 被3m多酶清洗液滴到皮肤怎么办 做3m赔了9万怎么办 在携程网上订的酒店发票怎么办 滴滴滴取消订单电话打不通怎么办 百度云容量2068g满了怎么办 淘宝电脑端描述图片间隔大怎么办 手机上下载游戏自动扣费怎么办 苹果手机下载游戏自动扣费怎么办 用手机账号登陆游戏换手机怎么办 在qq上被骗充q币怎么办 微信借钱后删了好友怎么办 财付通绑定了其它人的身份证怎么办 微信支付密码忘了没绑银行卡怎么办 微信没有绑银行卡忘记密码怎么办 威信解绑银行卡支付密码望了怎么办 买了个qq号绑定了财付通怎么办 淘宝买的东西下架了怎么办 微信红包充话费充错了怎么办 手机qq不能发红包或转账怎么办 qq给人发红包被骗了怎么办 qq发红包对方看不不到怎么办 手机浏览器支付页面弹不出来怎么办 新手机登录微信需要验证怎么办 手机淘宝注册账号换手机号后怎么办 冒充微信好友诈骗被骗了怎么办 刚刚激活的电信手机号码忘了怎么办 用手机充话费充错了怎么办 王者荣耀号丢了换成了别的号怎么办 微信给空号q币怎么办 qq密码被别人改了怎么办怎么登 qq刚改了密码忘了怎么办 qq密码忘了想改密码怎么办 qq账号和密码都忘了怎么办 我的微信被别人改了密码怎么办 微信被盗密码被改了怎么办 微信被盗了密码都被改了怎么办 微信被别人改密码改手机号了怎么办 微信号手机号码换了密码改了怎么办 电信充值卡的密码刮花了怎么办