Netty(三) 实现FTP服务器

使用Netty实现一个简单的FTP服务器

 

引入Netty的依赖

<dependency>
   <groupId>io.netty</groupId>
   <artifactId>netty-codec-http</artifactId>
   <version>4.1.45.Final</version>
</dependency>

服务端:

/**
 * @Author Joker
 * @Date 2020/11/15
 * @since 1.8
 */
public class HttpServerDemo {
    public static void main(String[] args) throws Exception {
        // 创建两个线程池
        NioEventLoopGroup acceptEventExecutors = new NioEventLoopGroup();
        NioEventLoopGroup readEventExecutors = new NioEventLoopGroup();

        // 1、创建ServerBootstrap
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        // 2.配置ServerBootstrap
        ChannelFuture channelFuture = serverBootstrap
                // 设置netty线程模型
                .group(acceptEventExecutors, readEventExecutors)
                // 设置Netty、类型
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer() {
                    @Override
                    protected void initChannel(Channel channel) throws Exception {
                        // 链式
                        ChannelPipeline pipeline = channel.pipeline();

                        // 添加入栈的处理器 ---》把ByteBuf转成字符串
                        pipeline.addLast(new HttpServerCodec());

                        // 添加入栈处理器 --》把字符串转成HttpFullRequest对象
                        pipeline.addLast(new HttpObjectAggregator(1024));

                        pipeline.addLast(new HttpServletRequest());
                    }
                })
                // 绑定端口的操作是异步的
                .bind(8888);
        // 阻塞
        channelFuture.sync();
        System.out.println("HTTP服务端启动成功。。。");
    }
}

 请求处理器(这里相比较前面代码多了一些):

/**
 * @Author Joker
 * @Date 2020/11/15
 * @since 1.8
 */
public class HttpServletRequest extends SimpleChannelInboundHandler<FullHttpRequest> {

    final String GET_REQUEST = "GET";

    // 文件夹路劲自己设一个就行  我这里乱写了一个我maven仓库地址
    final String FILE_PATH = "D:" + File.separator + "Maven-Repository";

    final String CONTEXT_TYPE = "Context-type";

    final String HTML_TYPE = "text/html;charset=UTF-8";

    final String CONTENT_LENGTH = "Content-Length";

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest request) throws Exception {

        // 获取用户的uri
        String uri = request.uri();
        String name = request.method().name();

        // 只支持GEt请求
        if (!GET_REQUEST.equals(name)) {
            // 响应浏览器
            responseError("只支持GET请求", channelHandlerContext);
            return;
        }

        File file = new File(FILE_PATH + URLDecoder.decode(uri, "UTF-8"));

        if (!file.exists()) {
            responseError("文件不存在。。。", channelHandlerContext);
            return;
        }

        if (file.isFile()) {
            // 如果是一个文件,就执行下载
            responseFileCopy(file, channelHandlerContext);
        } else {
            // 如果是一个目录就显示子目录
            responseDir(channelHandlerContext, file, uri);
        }

    }

    /**
     * 文件下载
     * @param file
     * @param channelHandlerContext
     */
    private void responseFileCopy(File file, ChannelHandlerContext channelHandlerContext) {

        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        response.headers().add(CONTEXT_TYPE, "application/octet-stream");
        response.headers().add(CONTENT_LENGTH, file.length());

        Channel channel = channelHandlerContext.channel();

        FileInputStream ips = null;
        try {
            ips = new FileInputStream(file);
            byte[] by = new byte[1024];
            int read = -1;
            while ((read = ips.read(by, 0, by.length)) != -1) {
                response.content().writeBytes(by, 0, read);
            }
            channel.writeAndFlush(response);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ips != null) {
                try {
                    ips.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 响应目录信息
     * @param channelHandlerContext
     * @param file
     * @param uri
     */
    private void responseDir(ChannelHandlerContext channelHandlerContext, File file, String uri) {

        StringBuffer buffer = new StringBuffer();
        // 获取目录的子文件
        File[] files = file.listFiles();

        for (File file1 : files) {
            if ("/".equals(uri)) {
                buffer.append("<li><a href= '" + uri + file1.getName() + "'>" + file1.getName() + "</a></li>");
            } else {
                buffer.append("<li><a href= '" + uri + File.separator + file1.getName() + "'>" + file1.getName() + "</a></li>");
            }
        }
        responseClient(buffer.toString(), channelHandlerContext);
    }

    /**
     * 响应客户端
     * @param text
     * @param channelHandlerContext
     */
    public void responseClient(String text, ChannelHandlerContext channelHandlerContext) {
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);

        // 设置响应头
        response.headers().add(CONTEXT_TYPE, HTML_TYPE);

        String msg = "<html> \t<meta charset=\"UTF-8\" />" + text + "</html>";

        try {
            response.content().writeBytes(msg.getBytes("UTF-8"));
            channelHandlerContext.channel().writeAndFlush(response);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 响应错误信息
     * @param text
     * @param channelHandlerContext
     */
    public void responseError(String text, ChannelHandlerContext channelHandlerContext) {
        String msg = "<h1>" + text + "</h1>";
        responseClient(msg, channelHandlerContext);
    }
}

启动服务器:

运行结果如下 一切顺利。。。

那么这就是一个简单的FTP服务器 , 现在我们可以通过访问IP来查看指定目录下的文件,以及下载文件 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
要使用Netty实现FTP服务器,可以按照以下步骤进行操作: 1. 创建一个新的Maven项目,并添加Netty的依赖。 2. 创建一个FTP服务器的主类。 3. 在主类中,创建一个ServerBootstrap实例,并设置相关的选项和处理程序。 4. 创建一个ChannelInitializer,用于配置管道,并添加FTP服务器的处理程序。 5. 创建FTP服务器的处理程序,继承自SimpleChannelInboundHandler,并实现相关的方法。 6. 实现FTP服务器的逻辑,包括处理用户身份验证、文件上传和下载等操作。 下面是一个简单的示例代码,演示了如何使用Netty实现一个简单的FTP服务器: ```java import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; public class FtpServer { private static final int PORT = 21; public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new FtpServerHandler()); } }); ChannelFuture future = serverBootstrap.bind(PORT).sync(); System.out.println("FTP server started on port " + PORT); future.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JokerQGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值