首頁>技術>

檔案伺服器

實現一個可以展示指定使用者輸入的檔案路徑,返回對應檔案內容的伺服器。

例項程式碼服務端
public class FileServer {    public static void main(String[] args) {        EventLoopGroup bossGroup = new NioEventLoopGroup();        EventLoopGroup workerGroup = new NioEventLoopGroup();        try {            ServerBootstrap serverBootstrap = new ServerBootstrap();            ChannelFuture channelFuture = serverBootstrap.group(bossGroup, workerGroup)                    .channel(NioServerSocketChannel.class)                    .childHandler(new ChannelInitializer<SocketChannel>() {                        @Override                        protected void initChannel(SocketChannel ch) throws Exception {                            // 編碼 String                            ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8))                                    // 按照行進行解碼                                    .addLast(new LineBasedFrameDecoder(1024))                                    // String 解碼                                    .addLast(new StringDecoder(CharsetUtil.UTF_8))                                    // 大資料流的處理                                    .addLast(new ChunkedWriteHandler())                                    .addLast(new FileServerHandler());                        }                    })                    .bind(8889)                    .syncUninterruptibly();            channelFuture.channel().closeFuture().syncUninterruptibly();        } finally {            workerGroup.shutdownGracefully();            bossGroup.shutdownGracefully();        }    }}
FileServerHandler.java

針對檔案伺服器的處理,實現如下:

import java.io.RandomAccessFile;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.handler.stream.ChunkedFile;public class FileServerHandler extends SimpleChannelInboundHandler<String> {    @Override    public void channelActive(ChannelHandlerContext ctx) throws Exception {        // 提醒客戶端輸入檔案路徑        ctx.writeAndFlush("HELLO: Type the path of the file to retrieve.\n");    }    @Override    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {        // 只讀方式開啟檔案        try(RandomAccessFile file = new RandomAccessFile(msg, "r")) {            long length = file.length();            ctx.write("OK: " + length + '\n');            ctx.write(new ChunkedFile(file));            ctx.writeAndFlush("\n");        }    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {        cause.printStackTrace();        ctx.close();    }}

整體比較簡單,exceptionCaught 為異常時的處理。

channelActive() 為客戶端連線時,服務端返回客戶端的提示。

channelRead0() 為服務端對於客戶端的反饋,就是透過客戶端輸入的檔案路徑,返回檔案內容。

測試驗證

我們直接使用本地的 telnet

開啟命令列

輸入 telnet localhost 8889

192:~ houbinbin$ telnet localhost 8889Trying ::1...Connected to localhost.Escape character is '^]'.HELLO: Type the path of the file to retrieve.
輸入檔案路徑
/Users/houbinbin/code/_github/netty-learn/netty-learn-four/src/main/java/com/github/houbb/netty/learn/four/file/FileServer.java

反饋如下:

就是把 FileServer.java 這個檔案內容全部返回回來了。

小結

可以發現基於 netty 實現一個檔案的讀寫工具其實並不難。

我當時的第一個感覺是可以實現一個日誌實時重新整理的介面,感興趣的小夥伴也可以自己實現以下。

我是老馬,期待與你的下次相遇。

14
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 使用Matplotlib繪製堆積條形圖