Java Sockets: как отправить несколько файлов с клиента на основе события на сервер - PullRequest
0 голосов
/ 07 апреля 2019

Я пишу программу, в которой клиент должен отслеживать создание файлов в определенной папке и отправлять их по мере их создания на сервер. Сервер всегда должен находиться в режиме прослушивания и сохранять эти файлы с тем же именем в указанномпапка на сервере. На данный момент я пытаюсь добиться этого на том же м / с. Как я могу добиться этого через сокет?

Я смог контролировать создание файлов в папке на клиентеи отправьте их. На приемнике я смог получить только один файл. После этого я получал исключение FileNotFoundException на сервере.

Код клиента

Socket sock = new Socket("localhost", 5991);  
        System.out.println("Connecting.........");

        Path faxFolder = Paths.get("C:\\Users\\Tushar Yadav\\Music\\src\\");
        WatchService watchService = FileSystems.getDefault().newWatchService();
        faxFolder.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);

        boolean valid = true;
        do {

            WatchKey watchKey = watchService.take();

            for (WatchEvent event : watchKey.pollEvents()) {
                WatchEvent.Kind kind = event.kind();
                if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
                    String fileName = event.context().toString();
                    System.out.println("File Created:" + fileName);

                    File myFile = new File("C:\\Users\\Tushar Yadav\\Music\\src\\"+fileName);

                    OutputStream os = sock.getOutputStream();  
                    DataOutputStream dos = new DataOutputStream(os);

                    dos.writeUTF(fileName);

                    dos.writeInt((int) myFile.length());

                    int filesize = (int) myFile.length();
                    byte [] buffer = new byte [filesize];

                    Thread.sleep(10000);
                    FileInputStream fis = new FileInputStream(myFile.toString());  
                    BufferedInputStream bis = new BufferedInputStream(fis);  

                    int count; 
                    while ((count = fis.read(buffer)) > 0) {
                        dos.write(buffer, 0, count);
                    }   

                    dos.flush(); 

                }
            }
            valid = watchKey.reset();

        }while (valid);

Код сервера

ServerSocket serverSocket = new ServerSocket(5991);
        Socket clientSocket = null;
        clientSocket = serverSocket.accept();

        in = clientSocket.getInputStream();  
        clientData = new DataInputStream(in); 
        clientBuff = new BufferedInputStream(in); 

        while(true){

            System.out.println("Starting...");  

            String fileName = clientData.readUTF();     

            System.out.println("filename : "+fileName);

            int fileSize = clientData.read();

            System.out.println("filesize is "+fileSize);

            len=fileSize;

            System.out.println("C:\\Users\\Tushar Yadav\\Music\\dest\\"+fileName);

            output = new FileOutputStream("C:\\Users\\Tushar Yadav\\Music\\dest\\"+fileName);

            dos=new DataOutputStream(output);
            bos=new BufferedOutputStream(output);

            byte[] buffer = new byte[1024];  

            bos.write(buffer, 0, buffer.length); 

            while (len > 0 && (smblen = clientData.read(buffer)) > 0) { 
                dos.write(buffer, 0, smblen); 
                len = len - smblen;
                dos.flush();
            }  
            dos.close();  

        }

Я ожидаю, что сервер подождет, пока клиент отправит другой файл, как только он будет создан на стороне клиента, но я получаю исключение filenotfound вскоре после того, как получатель получит и сохранит первый файл.

Кроме того, одно наблюдение состоит в том, что на стороне сервера я видел эту строку System.out.println("filename : "+fileName);, и последующие строки выполнялись дважды доxception выскакивает, несмотря на то, что на клиенте создается и отправляется только один файл.

Ниже приведены журналы кода сервера: -

Starting...
filename : New Text Document.txt
filesize is 0
C:\Users\Tushar Yadav\Music\dest\New Text Document.txt
Starting...
filename : 
filesize is 0
C:\Users\Tushar Yadav\Music\dest\
Exception in thread "main" java.io.FileNotFoundException: C:\Users\Tushar Yadav\Music\dest (Access is denied)
    at java.io.FileOutputStream.open0(Native Method)
    at java.io.FileOutputStream.open(Unknown Source)
    at java.io.FileOutputStream.<init>(Unknown Source)
    at java.io.FileOutputStream.<init>(Unknown Source)
    at test.Server.main(Server.java:55)

1 Ответ

0 голосов
/ 07 апреля 2019

В клиенте вы пишете размер файла с writeInt(), но на сервере вы читаете его с read().Вы должны использовать readInt().Это отбросило бы все, поскольку read() считывает только первый байт 4-байтовой целой длины;тогда вы не читаете никаких данных, потому что думаете, что длина равна 0;затем, когда вы пытаетесь прочитать имя второго файла, вы находитесь вне позиции и читаете пустую строку, что вызывает ошибку, которую вы видите.Кстати, вероятно, более правильно использовать writeLong() и readLong(), поскольку это тип возврата File.length(), но это зависит от вас, особенно если вы используете только файлы меньшего размера.

Там также, кажется,не соглашайтесь с тем, как вы используете DataOutputStream dos и BufferedOutputStream bos, оба из которых обертывают одинаковые FileOutputStream output.Сначала вы записываете полный неинициализированный буфер в файл через bos (только некоторые из которых могут быть записаны, поскольку они буферизуются);затем вы снова читаете и записываете фактические данные файла через dos, который добавит к тому, что было ранее записано в output.Может быть, вы имели в виду что-то вроде dos = new DataOutputStream(new BufferedOutputStream(output)), что даст вам преимущества обоих.Но вы все равно не хотите писать весь неинициализированный буфер перед циклом чтения, как вы это сделали.

Кроме того, поскольку вы используете только write(), вы, вероятно, можете напрямую использовать output.write() безмодный DataOutputStream.BufferedOutputStream полезен в качестве оптимизации, если вы хотите избежать частых небольших записей на диск, но в этом нет необходимости, особенно если учесть, что при чтении / записи фрагментов по 1 КБ существует некоторая внутренняя буферизация.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...