美文网首页
封装配置文件路径,定时使用socket传送文件到对应路径

封装配置文件路径,定时使用socket传送文件到对应路径

作者: 青休 | 来源:发表于2021-11-26 11:08 被阅读0次

    第一次使用socket进行文件传输,也踩了不少的小坑,不起眼但是会导致出现错误,记录一下踩坑经历。
    1、application.yml文件路径设置为List集合

    file:
      files[0]:
        sendPath: F:\fileTest\plmail\YWSQ
        receivePath: F:\fileTest\ecar\YWSQ
        suffix: _ok.txt
      files[1]:
        sendPath: F:\fileTest\plmail\FGYD
        receivePath: F:\fileTest\ecar\FGYD
        suffix: _ok.txt
    

    2、创建一个实体类存放配置,方便调用
    关于@ConfigurationProperties的用法参考:https://www.cnblogs.com/lihaoyang/p/10223339.html

    @Data
    public class AddrInfo {
        private String sendPath;
        private String receivePath;
        private String suffix;
    }
    
    @Data
    @Component
    @ConfigurationProperties(prefix = "file") 
    public class ECarConfig {
        private List<AddrInfo> files;
     }
    

    3、socket的客户端。服务器上如果开了防火墙,只允许特定端口访问的时候,需要设置端口复用,因为每一次访问都是socket动态分配端口,会被防火墙拦截。

    package gdems.com.transfer.ecar.config;
    
    import com.alibaba.fastjson.JSON;
    import gdems.com.transfer.ecar.TransParameter;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    
    import java.io.*;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    
    /**
     * @Auther:zjt
     * @Description:socket客户端
     */
    public class ECarClient extends Socket {
        private static final Logger logger = LoggerFactory.getLogger(ECarClient.class);
    
        private Socket socket;
        private FileInputStream fileInputStream;
        private DataOutputStream dataOutputStream;
        @Value("${local.port}")
        private int outPort;
    
        //创建客户端,并指定接收的服务端IP和端口号
        public ECarClient(String serverIp, int port) {
            this.socket = new Socket();
            try {
                //socket设置端口复用
                this.socket.setReuseAddress(true);
                this.socket.bind(new InetSocketAddress(outPort));
                this.socket.connect(new InetSocketAddress(serverIp, port));
            } catch (IOException e) {
                e.printStackTrace();
                try {
                    this.socket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            logger.info("成功连接服务端=====IP:" + serverIp + "端口号:" + port);
        }
    
        private ECarClient() throws IOException {
    
        }
    
        public boolean sendFile(File file, String receiveAddr) throws IOException {
            try {
                fileInputStream = new FileInputStream(file);
                dataOutputStream = new DataOutputStream(socket.getOutputStream());
                DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
                //文件名、大小属性等
                 /*
              省略部分:
                    1、获取文件上级目录
                    2、获取文件夹名称
                    3、最终获取后缀
                */
                dataOutputStream.writeUTF(JSON.toJSONString(new TransParameter(suffix, file.getName(), receiveAddr)));
                dataOutputStream.flush();
                dataOutputStream.writeLong(file.length());
                dataOutputStream.flush();
                //开始传输文件
                logger.info("======== 开始传输文件 ========");
                //分包传送,最后判断传输的大小是否与文件大小相同,以此来判断是否传输结束
                byte[] bytes = new byte[1024];
                int length = 0;
                boolean responseCode = false;
                while ((length = fileInputStream.read(bytes, 0, bytes.length)) != -1) {
                    dataOutputStream.write(bytes, 0, length);
                    dataOutputStream.flush();
                }
                 //需要释放socket的输出流,以便之后接收服务端的数据回传
                socket.shutdownOutput();
                String response = dataInputStream.readUTF();
                //服务端回传的接收状态,可在服务端自行修改回传的内容
                if (!"".equals(response)) {
                    responseCode = "OK".equals(response);
                }
                return responseCode;
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("客户端文件传输异常============" + e);
                return false;
            } finally {
                fileInputStream.close();
                dataOutputStream.close();
            }
        }
    }
    

    4、socket的服务端。

    package gdems.com.transfer.ecar.config;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * @Auther:zjt
     * @Date: 2021/9/7 17:43
     * @Description:socket服务端
     */
    @Component
    public class ECarFileServer implements Runnable {
        private static final Logger logger = LoggerFactory.getLogger(ECarFileServer.class);
    
        private static int SERVER_PORT = 9111; // 服务端端口
        private static ServerSocket server;
        private String url;
    
        public ECarFileServer() {
            try {
                if (server == null) {
                    server = new ServerSocket(SERVER_PORT);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("========ServerSocket:" + server.toString());
        }
    
        public ECarFileServer(String url) {
            this.url = url;
        }
    
        @Override
        public void run() {
            try {
                while (true) {
                    logger.info("=========端口号:" + SERVER_PORT + "等待连接 ========");
                    Socket socket = server.accept();
                    //这里的run是一个方法,不是线程的启动
                    new ECarTransfer(socket).run();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    }
    
    package gdems.com.transfer.ecar.config;
    
    import com.alibaba.fastjson.JSON;
    import gdems.com.transfer.ecar.TransParameter;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * @Auther:
     * @Date: 2021/9/23 16:55
     * @Description:
     */
    public class ECarTransfer implements Runnable {
        private static final Logger logger = LoggerFactory.getLogger(ECarFileServer.class);
        private Socket socket;
        private DataInputStream dataInputStream;
        private DataOutputStream dataOutputStream;
        private FileOutputStream fileOutputStream;
    
        public ECarTransfer(Socket socket) {
            this.socket = socket;
        }
    
    
        @Override
        public void run() {
            try {
                logger.info("ip" + socket.getInetAddress() + "已连接");
                dataInputStream = new DataInputStream(socket.getInputStream());
                dataOutputStream = new DataOutputStream(socket.getOutputStream());
    
                String content = dataInputStream.readUTF();
                TransParameter transParameter = JSON.parseObject(content, TransParameter.class);
                //传输文件地址后缀(省略)
                //根据文件路径和文件的后缀,匹配(省略)
                    fileOutputStream = new FileOutputStream(file);
    
                    logger.info("======== 开始接收文件 ========");
                    byte[] bytes = new byte[1024];
                    int length = 0;
                    while ((length = dataInputStream.read(bytes, 0, bytes.length)) != -1) {
                        fileOutputStream.write(bytes, 0, length);
                        fileOutputStream.flush();
                    }
                    dataOutputStream.writeUTF("OK");
                    logger.info("======== 文件接收成功 [File Name:" + transParameter.getFileName() + "] ");
                }
            } catch (Exception e) {
                logger.info("ECarServer is error ===== " + e);
                e.printStackTrace();
            } finally {
                try {
                    if (fileOutputStream != null)
                        fileOutputStream.close();
                    if (dataInputStream != null)
                        dataInputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    @Data
    @EqualsAndHashCode
    @NoArgsConstructor
    public class TransParameter implements Serializable {
        private String suffix;
        private String fileName;
        private String receiveAddr;
    
        public TransParameter(String suffix,String fileName,String receiveAddr) {
            this.suffix = suffix;
            this.fileName = fileName;
            this.receiveAddr = receiveAddr;
        }
    }
    

    5、编写一个配置类便于启动客户端和服务端

    package gdems.com.transfer.ecar.controller;
    
    import gdems.com.transfer.ecar.config.AddrInfo;
    import gdems.com.transfer.ecar.config.ECarClient;
    import gdems.com.transfer.ecar.config.ECarConfig;
    import gdems.com.transfer.ecar.util.FileUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Arrays;
    
    /**
     * @Auther:zjt
     * @Date: 2021/9/8 16:40
     * 
     */
    @Component
    @EnableScheduling
    @Slf4j
    public class ECarTrafficController {
        //服务器ip
        @Value("${receiver.address}")
        private String receiverAddress;
        //服务器port
        @Value("${socket.port}")
        private int socketPort;
    
        //定时器是否开启
        @Value("${trafficTimerOpen}")
        private boolean trafficTimerOpen;
    
        @Autowired
        private ECarConfig eCarConfig;
    
        @Scheduled(cron = "${scheduled.cron}")
        public void pushFile() {
            if (trafficTimerOpen) {
                   numberPlateApplication();
            }
        }
    
        public void numberPlateApplication() {
            try {
                for (AddrInfo addrInfo : eCarConfig.getFiles()) {
                    String sendPath = addrInfo.getSendPath();
                    String receivePath = addrInfo.getReceivePath();
                    String suffix = addrInfo.getSuffix();
    
                    //连接上本地服务器,获取文件
                    File[] fileArray = FileUtil.getFileArray(sendPath);
                    ArrayList<File> resultFiles = new ArrayList<>(Arrays.asList(fileArray));
                    resultFiles.removeIf(f -> !f.getName().endsWith(suffix));
                    if (resultFiles.size() > 0) {
                        log.info("开始推送===== " + sendPath + " 文件");
                        for (File file : fileArray) {
                            //调用socket文件流传送文件
                            ECarClient eCarClient = new ECarClient(receiverAddress, socketPort);
                            boolean isTrans = eCarClient.sendFile(file, receivePath);
                            if (isTrans) {
                                boolean delete = file.delete();
                                log.info(file.getAbsolutePath() + "删除" + delete);
                            }
                        }
                    } else {
                        log.info("===== " + sendPath + " 暂无数据推送=====");
                    }
                }
            } catch (IOException e) {
                log.info("TRAFFIC push files to EMS is IOException: " + e.getMessage());
            } catch (Exception e) {
                log.info("TRAFFIC push files to EMS is Exception: " + e.getMessage());
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:封装配置文件路径,定时使用socket传送文件到对应路径

          本文链接:https://www.haomeiwen.com/subject/lnvntrtx.html