Netty 基本使用,比Mina要稳定的多。

来源:互联网 发布:大数据风控模型 编辑:程序博客网 时间:2024/06/06 02:17

项目里有个聊天的功能,之前一直用mina,一直有一个bug没解决,那就是断包、少包、和粘包的问题。

谷歌度娘了很多文章,可惜都以失败而告终。

这个问题很奇怪,就算做了处理,还是不行。

以下情况会出现那个bug

第一:当客户端与服务器保持连接时,如果长时间未发送过长的较长的消息(心跳一直有)的情况下,突然发送一条较长的json字符串,就会出现这个问题

第二:当客户端频繁与服务器进行数据传送,也会出现这个问题。

原字符串:

{"message":{"content":"gghh ","msgid":"1413260146146","userlogo":"http:\/\/192.168.1."userlogo":"http:\/\/192.168.1.21:8888\/upload\/image\/201435\/e0feff917266411290f1.jpg","nickname":"申兵兵","msgtype":0,"receiverUid":"8",21:8888\/upload\/image\/201435\/e0feff917266411290f1.jpg","nickname":"申兵兵","msgtype":0,"receiverUid":"8","userid":"7","sendUid":"7","timel":0,"ctime":"2014-10-14 12:15:46"},"sendUid":"7","msgid":"1413260146146","cmd":"order_sendmessage","receiverUid":"8"}


接收到的字符串:

{"message":{"content":"gghh ","msgid":"1413260146146","userid":"7","sendUid":"7","timel":0,"ctime":"2014-10-14 12:15:46"},"sendUid":"7","msgid":"1413260146146","cmd":"order_sendmessage","receiverUid":"8"}

"userlogo":"http:\/\/192.168.1.21:8888\/upload\/image\/201435\/e0feff917266411290f1.jpg","nickname":"申兵兵","msgtype":0,"receiverUid":"8",

你没有看错,将会以两次来接收,第一次接收头和尾,第二次接收了中间的,真是莫名其妙。

后来改成了Netty,上手还是很快的。

添加 netty-all-5.0.0.Alpha1.jar 就可以了

首先启动服务,注意,一定要在线程里启动,不过加入你的整个项目只有一个简单的main方法的话,可以无视

        EventLoopGroup bossGroup = new NioEventLoopGroup();        EventLoopGroup workerGroup = new NioEventLoopGroup();        try {            ServerBootstrap b = new ServerBootstrap();            b.option(ChannelOption.SO_BACKLOG, 1024);            b.group(bossGroup, workerGroup)             .channel(NioServerSocketChannel.class)             .childHandler(new HttpHelloWorldServerInitializer());            Channel ch = b.bind(SocketManage.WORDPORT).sync().channel();            ch.closeFuture().sync();        }catch (Exception e) {e.printStackTrace();} finally {            bossGroup.shutdownGracefully();            workerGroup.shutdownGracefully();        }



HttpHelloWorldServerInitializer.class

public class HttpHelloWorldServerInitializer extends ChannelInitializer<SocketChannel> {    @Override    public void initChannel(SocketChannel ch) throws Exception {        ChannelPipeline pipeline = ch.pipeline();        pipeline.addLast("timeout", new IdleStateHandler(60, 15, 0));//定时        pipeline.addLast("framer", new DelimiterBasedFrameDecoder(                8192, Delimiters.lineDelimiter()));        pipeline.addLast("decoder", new StringDecoder(Charset.forName("utf-8")));        pipeline.addLast("encoder", new StringEncoder(Charset.forName("utf-8")));        pipeline.addLast("heartbeat", new MyHandler());//心跳        pipeline.addLast("handler",new HttpHelloWorldServerHandler());//业务    }}


MyHandler.class 就是拦截心跳和发送心跳的

public class MyHandler extends SimpleChannelInboundHandler<String> {     @Override     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {         if (evt instanceof IdleStateEvent) {             IdleStateEvent e = (IdleStateEvent) evt;             if (e.state() == IdleState.READER_IDLE) {//             System.out.println("--- Reader Idle ---");//               ctx.close();             } else if (e.state() == IdleState.WRITER_IDLE) {//             System.out.println("--- Write Idle ---");             ctx.writeAndFlush("#\n");             }         }     }@Overrideprotected void messageReceived(ChannelHandlerContext ctx, String str)throws Exception {if(str.equals("#")){return;}ctx.fireChannelRead(str);//传递到下一层,因为在HttpHelloWorldServerInitializer中注册了两个handelr,首先会进这里}}


HttpHelloWorldServerHandler.class 与上一个MyHandler是一样的

public class HttpHelloWorldServerHandler extends SimpleChannelInboundHandler<String> {   @Overrideprotected void messageReceived(ChannelHandlerContext ctx, String str)throws Exception {//str就是消息啦,在这里就可以进行业务逻辑了}}

大功告成!!注意发消息和接收消息都要以\n结尾。

0 0
原创粉丝点击