2 u010631191 u010631191 于 2017.01.11 12:36 提问

netty中怎么实现无限循环给每个客户端发数据?

正在做一个netty服务端,业务是这样的:客户端发数据给服务端,服务端收到之后发一条反馈数据回去;另外服务端需要实时查询数据库,如果有数据就发送给对应客户端,5秒循环一次,我把这两个业务写在同一个channelRead中,结果后者经常出现多次发送数据的情况,好像是多个线程都在执行这个循环,执行的周期不是5秒,5秒内执行了多次,也就是一条数据发了多次且次数不定,不知道是哪里的问题,感觉是自定义线程runnable和netty线程组之间没有协调工作,不知道怎么解决

 public class MyHandler extends ChannelHandlerAdapter {


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception 
            {
            01接收客户端数据,并给予反馈,代码略


            //02每五秒钟自动遍历一次数据库,将策略数据发送至指定客户端
        Runnable send = new Runnable() {
            @Override
            public void run() {
                Mysend:
                    //for无限循环
                    for(;;)
                    {
                        try{                
                            Convertion con=new Convertion();
                            gettacticsdata data=new gettacticsdata();
                            //读取存储在Map中已登录用户ID
                            Map<String, SocketChannel> map = Mymap.getChannels();

                            Iterator<String> it = map.keySet().iterator();
                            //for(int m=0;m<map.size();m++)
                            while (it.hasNext()) 
                            {
                                System.out.println("Map集合大小为:"+map.size());
                                String key = it.next();
                                System.out.println("key:"+key);
                                SocketChannel obj = map.get(key);
                                //判断当前客户是否在线,如果在线就传数据,不在就删除存储在Map中的登录信息
                                if(obj.isActive()==true)
                                {
                                    data.updatelwzt(key);
                                    //查询需要下发的策略B数据
                                    ArrayList Bal=data.GetBdata(key);
                                    //判断是否有需要下发的策略
                                    if(Bal.size()>0)
                                    {
                                        for(int i=0;i<Bal.size();i++)
                                        {
                                            tacticsBdata Bl=(tacticsBdata) Bal.get(i);
                                            byte[] Bdata=con.GetBdata(Bl);
                                            //SocketChannel obj = map.get(key);
                                            if(Bdata.length==32){
                                                ByteBuf Bsend =Unpooled.copiedBuffer(Bdata);
                                                obj.writeAndFlush(Bsend);
                                            }
                                        }       
                                    }
                                }else
                                {
                                    System.out.println("此ChannelID已掉线: " + obj);
                                    String resultdk=data.updatelwztdk(key);
                                    map.remove(key);
                                    obj.close();
                                }
                            }
                        }
                        catch(Exception e)
                        {
                            break Mysend;
                        }
                        try {
                            //线程休眠5秒钟后再次启动
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            //e.printStackTrace();
                        }
                    }
            }
        };
        new Thread(send).start();

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

1个回答

u012976158
u012976158   2017.01.11 15:12

我也正在做这个类似的通信,你的问题出现在,你从数据库获取的部分,你是一下把数据库中所有需要推送回客户端的数据都获取出来,然后遍历。因为你每次都是这样的操作,还有间隔几秒就会再次执行,但是当你数据库数据多的时候可能间隔的时间的处理不完所有的数据库命令,然后会再次获取执行,所以会重复。 解决方式:每次从数据库中获取一条,操作完,清除,下次也就几秒的时间,完全不影响大局,然后在获取一条,再操作

u010631191
u010631191 谢谢,我明白你的意思,我是一条数据发给一个客户端,经常出现发送多次,而且循环不是间隔5秒执行一次,有时一瞬间循环几次,好像有几个线程在执行,我感觉是我自定义的线程runnable和netty线程组之间没有协调的原因
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
Netty 服务器客户端,发送自定义消息
Netty 5 的包 服务器,四个java文件 1            SubReqServer.java package com.test.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.cha
Netty服务端与客户端依靠Java序列化传输数据
Netty服务端与客户端依靠Java序列化传输数据
【Netty】入门:客户端发送一个信息到服务器端,服务器端将信息原样返回
Java的I/O模型 我们知道java的I/O模型一共有四种,分别是:传统的BIO,伪异步I/O,NIO和AIO。 关于Netty   Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。...
Netty框架(一)————BIO编程
从这篇文章开始,将一步步探索Netty框架,从入门到精通,再到实际应用,我会把学到的总结下来,并与大家分享,如果有理解错误的地方,还请诸位大神予以纠正,希望与大家相互学习,共同进步,,还是那句话--“千里之行,始于足下”。 一、BIO编程     1、首先了解传统的BIO编程,我们所学的JAVA网络编程的基本模型是client/server模型,也就是两个进程之间进行相互通信,具体步骤是服务器
Netty数据传输-客户端,queue-client
【一个小程序员的成长日记】在公司接了一个任务,完成一个项目数据同步模块。要求是不能操作项目的数据库。所以想到的方案是使用log4jdbc记录数据源的SQL语句到日志文件。然后按行读取日志文件中的数据,记录读取的点,以便下次继续读取。读取的数据进入Big Queue队列(一个大型、快速且持久的队列),使用Netty将出队数据实时由客户端传输到服务端。传输后获取状态,判断状态,失败则重新传输。成功传输
netty客户端同步请求实现
netty客户端同步请求实现在项目开发中经常会遇到某个请求需要立刻返回结果的请,而我们使用的框架netty是异步的,如何做到同步请求是经常会困惑到刚刚接触netty的同行。 本文使用netty4为标准实现客户端向服务器的同步请求实例。如有不合理之处望各位指正,共同进步。 客户端 SimpleChatClientHandler package com.netty.chart;import jav
辛星netty4.1教程第二篇:区分不同的客户端
本教程源码托管在github上,地址: https://github.com/xinxing0913/netty-demo 。 有什么不清楚的可以加我微信:xinxing0913,备注”netty交流”就可以啦。 因为我们用netty写服务端代码的时候,一般我们都是编写的长连接应用,也就是我们是保存了客户端的状态的,这和写stateless的接口应用是完全不相同的体验,跟写通过Cookie和...
AAA基于netty TCP server server主动给client 发消息解决方案
思路 1 client 主动连接server ,server保存server和client的channel,并放在map里面,可以用java多线程的ConcurrentHashMap 2 当server想给client发消息的时候,拿到对应的key 从ConcurrentHashMap     TCPServerNetty.getMap().get(clientIP).write
Netty实现客户端和服务端的通信
Netty是Apache团队的又一个优秀的Socket框架,它和mina是一个团队开发的,所以很多思想是相同的,接下来,我们就来实现客户端和服务端的双向通信。        首先,我们定义消息类型:        /** * 消息类型 * @author 李熠 * */ public enum MsgType { PING,SEND,LOGIN,NO_TARGET }分别是心跳、发送、
关于龙哥在Netty课程中的FileChannel调用read方法返回0的原因解析
结论:fileChannel在调用read方法时会先对position和limit的值进行检查,如果limit与position的值相等或者position大于limit则直接返回0,不会再调用操作系统的read方法了。我们可以查看FileChannel抽象类的实现类FileChannelImpl中read(ByteBuffer byteBuffer)的源码:/* */ public...