netty的學(xué)習(xí)


title: netty的學(xué)習(xí)
tags: [netty]


最近寫android的tcp通信,用來傳輸文件,用原生的寫太麻煩了,還有開線程互相監(jiān)聽,一堆操作比較繁瑣,了解到netty比較好用,封裝的簡單,就用了這個來寫。
用的netty版本 'io.netty:netty-all:4.1.6.Final' ,
先注冊一個線程池 EventLoopGroup group =new NioEventLoopGroup();放在全局,

這里是服務(wù)端,只寫了接收信息

// MainApplication 里面的 因為這里是寫的android所以放到了MainApplication里面注冊的
EventLoopGroup group = MainApplication.getGroup();
ChannelFuture cf = MainApplication.getCf();
// 


public static ChannelFuture cf =MainApplication.getCf();
public static EventLoopGroup group = MainApplication.getGroup();
public static void  start(){
    try {
    Bootstrap b = new Bootstrap();
    b.group(group) // 注冊線程池
            .channel(NioSocketChannel.class)
            // 設(shè)置緩存區(qū)大小
    //                    .option(ChannelOption.RCVBUF_ALLOCATOR,
    //                            new AdaptiveRecvByteBufAllocator(64,1024,204800))
            // 使用NioSocketChannel來作為連接用的channel類
            .remoteAddress(new InetSocketAddress(host, port))
            // 綁定連接端口和host信息
            .handler(new ChannelInitializer<SocketChannel>() { // 綁定連接初始化器
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    Log.d(TAG, "initChannel: 正在連接中...");
                    // 設(shè)置好可以打印傳輸?shù)牧餍畔?    //                            ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
                    ch.pipeline().addLast(new StringEncoder(Charset.forName("UTF-8")));
                    // 實例化一個處理類,傳一些需要用到的參數(shù)參數(shù)
                    ch.pipeline().addLast(new ClientHandle(filePath, data, promise, host, port));
                    ch.pipeline().addLast(new ByteArrayEncoder());
                    ch.pipeline().addLast(new ChunkedWriteHandler());
                }
            });
    // System.out.println("服務(wù)端連接成功..");
    cf = b.connect().sync(); // 異步連接服務(wù)器
    cf.channel().closeFuture().sync();// 異步等待關(guān)閉連接channel
    }
    finally {
        // 最后執(zhí)行完可以釋放線程池,如果有多次操作就沒必要釋放了,
    //            group.shutdownGracefully().sync(); // 釋放線程池資源
    }
}


public class ClientHandle extends SimpleChannelInboundHandler<ByteBuf> {
    int fileSize = 0;
    private String TAG ="LoggingHandler";
    private DataOutputStream out;
    public ClientHandle(String filePath, Map data, String host, int port) throws FileNotFoundException {
        super();
        // 其他一些參數(shù)無視掉
        Log.e(TAG, "ClientHandle: "+"進來了ClientHandle");
        this.filePath = filePath;
        // 這里被實例化后就創(chuàng)建文件流。然后在下面寫入文件
        out = new DataOutputStream(
                new BufferedOutputStream(
                        new FileOutputStream(filePath)));
    }
    /**
     * 向服務(wù)端發(fā)送數(shù)據(jù)
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//        Log.d(TAG, "客戶端與服務(wù)端通道-開啟:" + ctx.channel().localAddress() +
//                "channelActive");
        Log.d(TAG, "channelActive: ");
        ctx.writeAndFlush(); // 可以發(fā)送流信息
    }
    /**
     * channelInactive
     *
     * channel 通道 Inactive 不活躍的
     *
     * 當(dāng)客戶端主動斷開服務(wù)端的鏈接后,這個通道就是不活躍的。也就是說客戶端與服務(wù)端的關(guān)閉了通信通道并且不可
     以傳輸數(shù)據(jù)
     *
     */
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
      
        Log.d(TAG, "客戶端與服務(wù)端通道-關(guān)閉:" + ctx.channel().localAddress() +
                "channelInactive");
    }
    // 這里讀取數(shù)據(jù),每次流進來就會觸發(fā)此函數(shù)
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
        // 這里msg當(dāng)然需要轉(zhuǎn)化下的,轉(zhuǎn)換格式根據(jù)服務(wù)端的編碼轉(zhuǎn)換
        out.write(msg)
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws
            Exception {
        ctx.close();
        cause.printStackTrace();
        Log.d(TAG, "異常退出");
    }
}

客戶端

這里可能有點不是很搭,但是畢竟好配合我們的業(yè)務(wù),因為客戶端是安裝在一個小板子上面的,板子存儲能力很弱,所有就選擇了node來做服務(wù)端來發(fā)送消息。

node tcp發(fā)送消息

var net = require('net');
net.createServer(function(socket){
    
    // socket.setKeepAlive(true, 1000);
  socket.on('data', function(data){
    transferUtils.resolveAndSendFile(data, socket);
  });
  socket.on('close',function () {
      console.log("client close");
  });
  socket.on('error', function(err){
    console.log("Socket transmit error!", err);
  })
  // 監(jiān)聽15000端口
}).listen(15000, "0.0.0.0");  

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容