Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,25 @@
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>16-ea+1</version>
</dependency>
</dependencies>
</project>
81 changes: 81 additions & 0 deletions client/src/main/java/ClientHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;

public class ClientHandler extends ChannelInboundHandlerAdapter {

private int nextLength;//размер следующего куска ожидаемого файла
private long fileLength;//длина файла
private long receivedFileLength;//сколько байт уже получено
private BufferedOutputStream out;//запись байтов в файл

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = ((ByteBuf) msg);
while (buf.readableBytes() > 0) {//если пришло сообщение, пытаемся понять что это за сообщение
byte readed = buf.readByte();//вычитываем первый сигнальный байт
if (readed == 25) {//если пришел сигнальный байт соответствующий получению файла
receivedFileLength = 0L;//считаем то не получили ни одного байта от присылаемого файла
System.out.println("STATE CL: Start file receiving");//сообщаем о старте передачи файла
gettingFileNameLength(buf);//получаем длину имени файла
byte[] fileName = getFileName(buf);//получаем имя файла
System.out.println("STATE CL: Filename received - " + new String(fileName, "UTF-8"));//собираем из байтового массива строку с именем файла
out = new BufferedOutputStream(new FileOutputStream("client_storage/" + new String(fileName)));//открываем BufferedOutputStream для получения данных файла
gettingFileLength(buf);//получаем длину файла
getFile(buf);//получаем файл

// } else {
// System.out.println("ERROR CL: Invalid first byte - " + readed);//сообщаем об ошибке
}
// if (buf.readableBytes()==0){buf.release();}
}
}

//получаем длину имени файла
private void gettingFileNameLength(ByteBuf buf) {
if (buf.readableBytes() >= 4) {//пришло более 4 байт (длина имени файла = 1 int)
System.out.println("STATE CL: Get filename length");
nextLength = buf.readInt();//вычитываем из входящего буфера 1 int
}
}

//получаем имя файла
private byte[] getFileName(ByteBuf buf) throws Exception {
byte[] fileName = new byte[nextLength];//формируем байтовый массив для имени
if (buf.readableBytes() >= nextLength) {//проверяем есть ли в буфере байтов столько сколько в длине имени что бы не прочитать только часть имени файла
buf.readBytes(fileName);//вычитываем из буфера байты в байтовый массив
}
return fileName;
}

//получаем длину файла
private void gettingFileLength(ByteBuf buf) {
if (buf.readableBytes() >= 8) {//если пришло более 8 байт (длина файла = 1 long)
fileLength = buf.readLong();//вычитываем из буфера 1 long (длину файла)
System.out.println("STATE CL: File length received - " + fileLength);
}
}

//получаем файл

private void getFile(ByteBuf buf) throws Exception {
while (buf.readableBytes() > 0) {//если в буфере есть непрочитанные байты
out.write(buf.readByte());//пишем побайтово непрочитанные байты в файл
receivedFileLength++;//говорим что получили еще один байт (подсчитываем количество полученных байтов)
if (fileLength == receivedFileLength) {//если длина ожидаемого файла равна количеству полученных байтов
System.out.println("CL File received");
out.close();//закрываем файл в который писали байты
break;//останавливаем получение
}
}
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
116 changes: 82 additions & 34 deletions client/src/main/java/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@

import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.CountDownLatch;

import static java.lang.Thread.currentThread;

public class Controller implements Initializable {
@FXML
Expand All @@ -38,47 +43,89 @@ public void authorization(ActionEvent actionEvent) {
}

public void initialize(URL location, ResourceBundle resources) {//инплементированный метод
Network.start();
Thread t = new Thread(() -> {//демон поток ожидающий файлы от сервера
try {
while (true) {
AbstractMessage am = Network.readObject();//ожидает любые сообщения от сервера
if (am instanceof FileMessage) {//если сервер прислал FileMessage
FileMessage fm = (FileMessage) am;//кастует полученное сообщение к FileMessage
Files.write(Paths.get("client_storage/"
+ fm.getFilename()), fm.getData(), StandardOpenOption.CREATE);//записывает полученный файл в client_storage
refreshLocalFilesList();//обновляет список файлов в client_storage
}
}
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
} finally {
Network.stop();
}
});
t.setDaemon(true);
t.start();
CountDownLatch networkStarter = new CountDownLatch(1);//создание защелки на 1 щелчок
new Thread(() -> Network.getInstance().start(networkStarter)).start();//запуск сети в отдельном потоке
try {
networkStarter.await();//ожидает открытия сетевого соединения
} catch (InterruptedException e) {
e.printStackTrace();
}
refreshLocalFilesList();
}

//действие по кнопке downloadServerButton. Загрузка файла на сервер
public void downloadFileServer (ActionEvent actionEvent) {
if (fileNameField.getLength() > 0) {
Network.sendMsg(new FileRequest(fileNameField.getText()));//клиент посылает серверу FileRequest с именем интересующего файла
fileNameField.clear();//очищает форму в интерфейсе
}
//Получение файла с сервера
public void uploadFileClient(ActionEvent actionEvent) throws Exception {
ProtoFileSender.requestFile(Paths.get(fileNameField.getText()), Network.getInstance().getCurrentChannel(), future -> {
if (!future.isSuccess()) {//действие при неудачном получении файла
future.cause().printStackTrace();
// Network.getInstance().stop();
}
if (future.isSuccess()) {//действие при удачном получении файла
System.out.println("Файл успешно получен");
// Network.getInstance().stop();
}
});
fileNameField.clear();//очищает форму в интерфейсе
}

//действие по кнопке uploadServerButton. Загрузка файла на клиент
public void uploadFileClient(ActionEvent actionEvent) throws IOException {
if (fileNameField.getLength() > 0) {
if (Files.exists(Paths.get("client_storage/" + fileNameField.getText()))) {
Network.sendMsg(new FileMessage(Paths.get("client_storage/" + fileNameField.getText())));
fileNameField.clear();
//Отправка файла на сервер
public void downloadFileServer(ActionEvent actionEvent) throws Exception {
//Действия по finishListener (из ProtoFileSender, метод sendFile)
ProtoFileSender.sendFile(Paths.get("client_storage/" + fileNameField.getText()), Network.getInstance().getCurrentChannel(), future -> {//указываем файл и сеть для отправки
if (!future.isSuccess()) {//действие при неудачной передаче файла
future.cause().printStackTrace();
// Network.getInstance().stop();
}
}
if (future.isSuccess()) {//действие при удачной передаче файла
System.out.println("Файл успешно передан");
// Network.getInstance().stop();
}
});
fileNameField.clear();//очищает форму в интерфейсе
}


// Network.start();
// Thread t = new Thread(() -> {//демон поток ожидающий файлы от сервера
// try {
// while (true) {
// AbstractMessage am = Network.readObject();//ожидает любые сообщения от сервера
// if (am instanceof FileMessage) {//если сервер прислал FileMessage
// FileMessage fm = (FileMessage) am;//кастует полученное сообщение к FileMessage
// Files.write(Paths.get("client_storage/"
// + fm.getFilename()), fm.getData(), StandardOpenOption.CREATE);//записывает полученный файл в client_storage
// refreshLocalFilesList();//обновляет список файлов в client_storage
// }
// }
// } catch (ClassNotFoundException | IOException e) {
// e.printStackTrace();
// } finally {
// Network.stop();
// }
// });
// t.setDaemon(true);
// t.start();
// refreshLocalFilesList();
// }

// //действие по кнопке downloadServerButton. Загрузка файла на сервер
// public void downloadFileServer (ActionEvent actionEvent) {
// if (fileNameField.getLength() > 0) {
// Network.sendMsg(new FileRequest(fileNameField.getText()));//клиент посылает серверу FileRequest с именем интересующего файла
// fileNameField.clear();//очищает форму в интерфейсе
// }
// }
//
// //действие по кнопке uploadServerButton. Загрузка файла на клиент
// public void uploadFileClient(ActionEvent actionEvent) throws IOException {
// if (fileNameField.getLength() > 0) {
// if (Files.exists(Paths.get("client_storage/" + fileNameField.getText()))) {
// Network.sendMsg(new FileMessage(Paths.get("client_storage/" + fileNameField.getText())));
// fileNameField.clear();
// }
// }
// }
//
//обновление списка локальных файлов
public void refreshLocalFilesList() {
Platform.runLater(() -> {
Expand All @@ -93,5 +140,6 @@ public void refreshLocalFilesList() {
}
});
}

}


86 changes: 43 additions & 43 deletions client/src/main/java/Network.java
Original file line number Diff line number Diff line change
@@ -1,58 +1,58 @@

import io.netty.handler.codec.serialization.ObjectDecoderInputStream;
import io.netty.handler.codec.serialization.ObjectEncoderOutputStream;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.io.IOException;
import java.net.Socket;
import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;

public class Network {
private static Socket socket;
private static ObjectEncoderOutputStream out;//исходящий поток для отправки
private static ObjectDecoderInputStream in;//входящий поток для получения
private static Network ourInstance = new Network();

public static void start() {
try {
socket = new Socket("localhost", 8189);
out = new ObjectEncoderOutputStream(socket.getOutputStream());
in = new ObjectDecoderInputStream(socket.getInputStream(), 50 * 1024 * 1024);
} catch (IOException e) {
e.printStackTrace();
}
public static Network getInstance() {
return ourInstance;
}

public static void stop() {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
private Network() {
}

private Channel currentChannel;//канал передачи

public Channel getCurrentChannel() {
return currentChannel;
}

//позволяет отправлять любые сообщения серверу
public static boolean sendMsg(AbstractMessage msg) {
public void start(CountDownLatch countDownLatch) {
EventLoopGroup group = new NioEventLoopGroup();
try {
out.writeObject(msg);
return true;// если успешная отправка сообщения
} catch (IOException e) {
Bootstrap clientBootstrap = new Bootstrap();//настройка клиента
clientBootstrap.group(group)//ссылка на пул потоков
.channel(NioSocketChannel.class)//работа через NioSocketChannel
.remoteAddress(new InetSocketAddress("localhost", 8189))//адрес соединения
.handler(new ChannelInitializer<SocketChannel>() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new ClientHandler());
currentChannel = socketChannel;//ссылка на socketChannel
}
});
ChannelFuture channelFuture = clientBootstrap.connect().sync();//создается подключение
countDownLatch.countDown();//подключение открывается
channelFuture.channel().closeFuture().sync();//ожидание завершения подключения
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
group.shutdownGracefully().sync();//завершает пул потоков
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return false;//если не удалось отправить сообщение
}


//получение объектов от сервера
public static AbstractMessage readObject() throws ClassNotFoundException, IOException {
Object obj = in.readObject();//блокирующая операция, может ожидать посылки от сервера
return (AbstractMessage) obj;//возвращает полученный от сервера объект
}
}
public void stop() {
currentChannel.close();
}//метод остановки сети
}
Loading