You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
6.0 KiB
159 lines
6.0 KiB
2 years ago
|
/*
|
||
|
* Демонстрационное приложение.
|
||
|
*/
|
||
|
package udp;
|
||
|
|
||
|
import java.io.BufferedReader;
|
||
|
import java.io.FileOutputStream;
|
||
|
import java.io.IOException;
|
||
|
import java.io.InputStreamReader;
|
||
|
import java.net.DatagramPacket;
|
||
|
import java.net.DatagramSocket;
|
||
|
import java.net.InetAddress;
|
||
|
import java.net.SocketException;
|
||
|
import java.nio.ByteBuffer;
|
||
|
|
||
|
/**
|
||
|
* Класс клиента. Реализует запрос и получение файла от сервера.
|
||
|
*
|
||
|
* @author (C)Y.D.Zakovryashin, 16.01.2023
|
||
|
*/
|
||
|
public class UDPClient {
|
||
|
|
||
|
private DatagramSocket socket;
|
||
|
private DatagramPacket packet;
|
||
|
private byte[] buffer;
|
||
|
private String fileName;
|
||
|
|
||
|
public static void main(String[] args) {
|
||
|
System.out.println("Client started...");
|
||
|
try (DatagramSocket s = new DatagramSocket()) {
|
||
|
UDPClient client = new UDPClient();
|
||
|
client.socket = s;
|
||
|
/**
|
||
|
* Запрос у пользователя имени файла для загрузки.
|
||
|
*/
|
||
|
client.getFileName();
|
||
|
/**
|
||
|
* Запрос файла с сервера.
|
||
|
*/
|
||
|
client.sendFileName();
|
||
|
/**
|
||
|
* Чтение ответа сервера, содержащего либо размер файла, либо код
|
||
|
* ERROR, который означает отсутствие запрошенного файла на сервере.
|
||
|
*/
|
||
|
long size = client.getFileSize();
|
||
|
if (size > UDPServer.ERROR) {
|
||
|
try {
|
||
|
/**
|
||
|
* Загрузка файла с сервера.
|
||
|
*/
|
||
|
client.getFile(size);
|
||
|
System.out.println("File \"" + client.fileName
|
||
|
+ "\" is downloaded successfully.");
|
||
|
} catch (IOException e) {
|
||
|
/**
|
||
|
* Произошла ошибка чтения файла.
|
||
|
*/
|
||
|
System.err.println("File \"" + client.fileName
|
||
|
+ "\" isn\'t downloaded.\n" + e.getMessage());
|
||
|
}
|
||
|
} else {
|
||
|
/**
|
||
|
* Сервер вернул код ERROR, который означает, что на сервере нет
|
||
|
* файла с запрошенным именем.
|
||
|
*/
|
||
|
System.out.println("File \"" + client.fileName + "\" not found");
|
||
|
}
|
||
|
} catch (SocketException ex) {
|
||
|
System.out.println("Error #1: " + ex.getMessage());
|
||
|
} catch (IOException ex) {
|
||
|
System.out.println("Error #2: " + ex.getMessage());
|
||
|
}
|
||
|
System.out.println("Client stoped.");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Чтение имени запрашиваемого файла с консоли.
|
||
|
*
|
||
|
* @return строку с именем файла.
|
||
|
*/
|
||
|
private void getFileName() {
|
||
|
try (BufferedReader in = new BufferedReader(
|
||
|
new InputStreamReader(System.in));) {
|
||
|
/**
|
||
|
* Цикл запроса имени файла должен выполняться до тех пор, пока
|
||
|
* пользователь не введёт непустое имя файла.
|
||
|
*/
|
||
|
do {
|
||
|
System.out.println(">>> Input file name for download:");
|
||
|
fileName = in.readLine();
|
||
|
} while (fileName == null || fileName.trim().isEmpty());
|
||
|
} catch (IOException e) {
|
||
|
System.out.println("Errror: " + e.getMessage());
|
||
|
}
|
||
|
System.out.println("Step 1");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Отправка запроса с именем файла.
|
||
|
*
|
||
|
* @param fileName строка с именем файла.
|
||
|
* @throws IOException в случае общей ошибки ввода/вывода.
|
||
|
*/
|
||
|
private void sendFileName() throws IOException {
|
||
|
buffer = fileName.getBytes();
|
||
|
/**
|
||
|
* В пакет заносится адрес сервера, его порт и сериализованное имя
|
||
|
* файла.
|
||
|
*/
|
||
|
packet = new DatagramPacket(buffer, buffer.length,
|
||
|
InetAddress.getByName(UDPServer.UDP_SERVER_ADDRESS),
|
||
|
UDPServer.UDP_SERVER_PORT);
|
||
|
socket.send(packet);
|
||
|
System.out.println("Step 2");
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Получение первого пакета от сервера с размером файла и отправка пакета с
|
||
|
* подтверждением о готовности принять файл.
|
||
|
*
|
||
|
* @return размер файла.
|
||
|
* @throws IOException в случае общей ошибки ввода/вывода.
|
||
|
*/
|
||
|
private long getFileSize() throws IOException {
|
||
|
buffer = new byte[8];
|
||
|
packet = new DatagramPacket(buffer, buffer.length);
|
||
|
/**
|
||
|
* Получение пакета с размером файла.
|
||
|
*/
|
||
|
socket.receive(packet);
|
||
|
long size = ByteBuffer.wrap(packet.getData()).getLong();
|
||
|
if (size > UDPServer.ERROR && size < Integer.MAX_VALUE) {
|
||
|
buffer = UDPServer.OK.getBytes();
|
||
|
} else {
|
||
|
buffer = UDPServer.NO.getBytes();
|
||
|
}
|
||
|
/**
|
||
|
* Подготовка и отправка пакета с подтверждением о готовности принять
|
||
|
* файл.
|
||
|
*/
|
||
|
packet.setData(buffer);
|
||
|
packet.setLength(buffer.length);
|
||
|
socket.send(packet);
|
||
|
System.out.println("Step 3");
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
private void getFile(long size) throws IOException {
|
||
|
int s = size > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) size;
|
||
|
buffer = new byte[s];
|
||
|
packet.setData(buffer);
|
||
|
socket.receive(packet);
|
||
|
try (FileOutputStream fos = new FileOutputStream("Copy-" + fileName)) {
|
||
|
fos.write(buffer);
|
||
|
}
|
||
|
System.out.println("Step 4");
|
||
|
}
|
||
|
}
|