#java #sockets
#java #сокеты
Вопрос:
Я пишу программу, в которой клиенту необходимо отслеживать создание файлов в определенной папке и отправлять их по мере их создания на сервер.Сервер всегда должен находиться в режиме прослушивания и сохранять эти файлы с одинаковыми именами в указанной папке на сервере.На данный момент я пытаюсь достичь этого на том же m / c. Как мне достичь этого через сокет?
Я смог отслеживать создание файлов в папке на клиенте и отправлять их.На приемнике я смог получить только один файл.После этого я получал исключение 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 amp;amp; (smblen = clientData.read(buffer)) > 0) {
dos.write(buffer, 0, smblen);
len = len - smblen;
dos.flush();
}
dos.close();
}
Я ожидаю, что сервер будет ждать, пока клиент отправит другой файл, как только он будет создан на стороне клиента, но я получаю исключение filenotfound вскоре после того, как получатель получил и сохранил первый файл.
Кроме того, одно наблюдение заключается в том, что на стороне сервера я видел, что эта строка System.out.println("filename : " fileName);
и последующие строки выполняются дважды, пока не появится исключение, несмотря на создание (и неотъемлемую отправку) только одного файла на клиенте.
Ниже приведены журналы для серверного кода:-
Starting...
filename : New Text Document.txt
filesize is 0
C:UsersTushar YadavMusicdestNew Text Document.txt
Starting...
filename :
filesize is 0
C:UsersTushar YadavMusicdest
Exception in thread "main" java.io.FileNotFoundException: C:UsersTushar YadavMusicdest (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:
В клиенте вы указываете размер файла с помощью writeInt()
, но на сервере вы его считываете с помощью read()
. Вы должны использовать readInt()
. Это отбросило бы все, поскольку read()
считывается только первый байт из 4-байтовой целочисленной длины; затем вы не считываете никаких данных, потому что считаете, что длина равна 0; затем, когда вы пытаетесь прочитать имя 2-го файла, вы теряете позицию и читаете пустую строку, что вызывает ошибку, которую вы видите. Кстати, вероятно, правильнее использовать writeLong()
and readLong()
, поскольку это возвращаемый тип File.length()
, но это зависит от вас, особенно если вы используете только файлы меньшего размера.
Также, кажется, что-то не так с тем, как вы используете DataOutputStream dos
и BufferedOutputStream bos
, оба из которых заключают в себе одно и то же FileOutputStream output
. Сначала вы записываете полный неинициализированный буфер в файл через bos
(только часть из которых действительно может быть записана, поскольку она буферизована); затем вы снова считываете и записываете фактические данные файла через dos
, которые будут добавлены к тому, что было ранее записано в output
. Возможно, вы имели в виду что-то вроде dos = new DataOutputStream(new BufferedOutputStream(output))
, что дало бы вам преимущества обоих. Но вы по-прежнему не хотите записывать весь неинициализированный буфер перед циклом чтения, как вы сделали.
Кроме того, поскольку вы используете только write()
, вы, вероятно, могли бы использовать напрямую output.write()
без навороченного DataOutputStream. BufferedOutputStream полезен в качестве оптимизации, если вы хотите избежать частых небольших записей на диск, но в этом нет необходимости, тем более что при чтении / записи фрагментов размером 1 КБ существует некоторая внутренняя буферизация.