1. 程式人生 > >netty4.x 傳輸文件

netty4.x 傳輸文件

hand active pid con dom pat setfile color bsp

一:簡介

netty傳輸文件的例子並不多,當前的項目剛才需要使用netty,所以就記錄一下使用方法,使用netty傳輸文件,首先需要啟動一個服務端,等待服務端請求監聽,然後傳輸文件的時候,啟動一個客戶端線程來傳輸文件。

二:啟動一個服務端等待監聽

1):引入netty版本號

<dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.15.Final</version>
        </dependency>

2):啟動一個服務端

//聲明兩個多線程事件循環器
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
//聲明nio服務啟動類
ServerBootstrap serverBootstrap = new ServerBootstrap ();
 b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024).childHandler(new
ChannelInitializer<Channel>() { @Override protected void initChannel(Channel ch) throws Exception { System.out.println("有客戶端連接上來:"+ch.localAddress().toString()); ch.pipeline().addLast(new ObjectEncoder()); ch.pipeline().addLast(
new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.weakCachingConcurrentResolver(null))); // 最大長度 ch.pipeline().addLast(new FileUploadServerHandler()); } }); ChannelFuture f = b.bind(port).sync();//邦定端口並啟動 System.out.println("file server 等待連接:"); f.channel().closeFuture().sync();

3):接收文件的handler extends ChannelInboundHandlerAdapter,在channelRead方法中獲取文件

//自定義的一個對像,保存文件相關的屬性
FileUploadFile ef = (FileUploadFile) msg;
            byte[] bytes = ef.getBytes();
            byteRead = ef.getEndPos();
            String md5 = ef.getFile_md5();//文件名
         //讀文件的相關代碼
String path = file_dir + File.separator + md5;
            File file = new File(path);
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
            randomAccessFile.seek(start);
            randomAccessFile.write(bytes);
            start = start + byteRead;
            System.out.println("path:"+path+","+byteRead);
            if (byteRead > 0) {
                ctx.writeAndFlush(start);
                randomAccessFile.close();
                if(byteRead!=1024 * 10){//測試每次讀取10k,當文件大小不是10k時,默認文件讀完, 這裏可以不用調用channelInactive()
                    Thread.sleep(1000);
                    channelInactive(ctx);
                }
            } else {
                //System.out.println("文件接收完成");
                //ctx.flush(); 
                ctx.close();
            }
            
        }

        

服務端的代碼大致就是這些,我們來看客戶端的代碼。

4:) 初始化客戶端

//客戶端只創建一個事件循環處理器
EventLoopGroup group = new NioEventLoopGroup();
try {
            Bootstrap b = new Bootstrap();
//註意這裏和服務端的區別,服務端:NioServerSocketChannel,客戶端:NioSocketChannel
b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
.handler(
new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(
new ObjectEncoder());
ch.pipeline() .addLast(
new ObjectDecoder( ClassResolvers .weakCachingConcurrentResolver(null)));
ch.pipeline() .addLast(
new FileUploadClientHandler( fileUploadFile)); } });
ChannelFuture f
= b.connect(host, port).sync(); //連接服務端
f.channel().closeFuture().sync();//關閉

5:)上傳文件的handler同樣繼承為 ChannelInboundHandlerAdapter

在channelInactive方法將文件相關信息,如:文件名,文件長度等封裝一個對像,輸出至服務端

FileUploadFile uploadFile = new FileUploadFile();
File file = new File("d:/source.rar");
String fileMd5 = file.getName();// 文件名
uploadFile.setFile(file);
uploadFile.setFile_md5(fileMd5);

在channelRead方法來讀取和上傳文件流

randomAccessFile = new RandomAccessFile(
                        fileUploadFile.getFile(), "r");
randomAccessFile.seek(start);
fileUploadFile.setEndPos(byteRead);
fileUploadFile.setBytes(bytes);
    try {
        ctx.writeAndFlush(fileUploadFile);
    } catch (Exception e) {
        e.printStackTrace();
    }

主要的代碼就是這些,demo下載地址:github

netty4.x 傳輸文件