diff --git a/client/pom.xml b/client/pom.xml
index 342bc8c..eedcb66 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -34,5 +34,25 @@
1.0-SNAPSHOT
compile
+
+ org.openjfx
+ javafx-base
+ 11.0.2
+
+
+ org.openjfx
+ javafx-graphics
+ 11.0.2
+
+
+ org.openjfx
+ javafx-controls
+ 11.0.2
+
+
+ org.openjfx
+ javafx-fxml
+ 16-ea+1
+
\ No newline at end of file
diff --git a/client/src/main/java/ClientHandler.java b/client/src/main/java/ClientHandler.java
new file mode 100644
index 0000000..e30fde3
--- /dev/null
+++ b/client/src/main/java/ClientHandler.java
@@ -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();
+ }
+}
diff --git a/client/src/main/java/Controller.java b/client/src/main/java/Controller.java
index 34f0376..82967ca 100644
--- a/client/src/main/java/Controller.java
+++ b/client/src/main/java/Controller.java
@@ -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
@@ -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(() -> {
@@ -93,5 +140,6 @@ public void refreshLocalFilesList() {
}
});
}
-
}
+
+
diff --git a/client/src/main/java/Network.java b/client/src/main/java/Network.java
index 7877d98..2972a5d 100644
--- a/client/src/main/java/Network.java
+++ b/client/src/main/java/Network.java
@@ -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() {
+ 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();
+ }//метод остановки сети
+}
\ No newline at end of file
diff --git a/client/src/main/resources/sample.fxml b/client/src/main/resources/sample.fxml
index ff73535..2ef7e00 100644
--- a/client/src/main/resources/sample.fxml
+++ b/client/src/main/resources/sample.fxml
@@ -7,12 +7,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
@@ -27,5 +27,4 @@
-
diff --git a/common/pom.xml b/common/pom.xml
index 75367a8..4aaa3d2 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -16,11 +16,18 @@
org.apache.maven.plugins
maven-compiler-plugin
- 7
- 7
+ 8
+ 8
+
+
+ io.netty
+ netty-all
+ 4.1.42.Final
+
+
\ No newline at end of file
diff --git a/common/src/main/java/AbstractMessage.java b/common/src/main/java/AbstractMessage.java
deleted file mode 100644
index 6f3419e..0000000
--- a/common/src/main/java/AbstractMessage.java
+++ /dev/null
@@ -1,6 +0,0 @@
-
-import java.io.Serializable;
-
-//Класс сообщения для обмена между клиентом и сервером
-public abstract class AbstractMessage implements Serializable {
-}
\ No newline at end of file
diff --git a/common/src/main/java/FileMessage.java b/common/src/main/java/FileMessage.java
deleted file mode 100644
index c9dea67..0000000
--- a/common/src/main/java/FileMessage.java
+++ /dev/null
@@ -1,22 +0,0 @@
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-public class FileMessage extends AbstractMessage {
- private String filename;//имия файла
- private byte[] data;//файловый массив(тело файла)
-
- public String getFilename() {
- return filename;
- }
-
- public byte[] getData() {
- return data;
- }
-
- public FileMessage(Path path) throws IOException {//путь к файлу из которого можно создать FileMessage
- filename = path.getFileName().toString();
- data = Files.readAllBytes(path);
- }
-}
diff --git a/common/src/main/java/FileRequest.java b/common/src/main/java/FileRequest.java
deleted file mode 100644
index 6824adb..0000000
--- a/common/src/main/java/FileRequest.java
+++ /dev/null
@@ -1,12 +0,0 @@
-
-public class FileRequest extends AbstractMessage {
- private String filename;// имя файла по которому сервер понимает что хочет клиент
-
- public String getFilename() {
- return filename;
- }
-
- public FileRequest(String filename) {
- this.filename = filename;
- }
-}
\ No newline at end of file
diff --git a/common/src/main/java/ProtoFileSender.java b/common/src/main/java/ProtoFileSender.java
new file mode 100644
index 0000000..c1f66d0
--- /dev/null
+++ b/common/src/main/java/ProtoFileSender.java
@@ -0,0 +1,64 @@
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.channel.*;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+
+//как отправляются данные
+public class ProtoFileSender {
+ public static void sendFile(Path path, Channel channel, ChannelFutureListener finishListener) throws IOException {
+ FileRegion region = new DefaultFileRegion(path.toFile(), 0, Files.size(path));//создаем ссылку на кусок отправляемого файла (путь к файлу, начало куска, размер куска)
+
+ byte[] fileNameBytes = path.getFileName().toString().getBytes(StandardCharsets.UTF_8);
+ ByteBuf buf = ByteBufAllocator.DEFAULT.directBuffer(1+4+fileNameBytes.length+8);
+ buf.writeByte((byte)25);//сигнальный байт
+ buf.writeInt(fileNameBytes.length);//длина имени файла
+ buf.writeBytes(fileNameBytes);//имя файла
+ buf.writeLong(Files.size(path));//размер файла
+ channel.writeAndFlush(buf);//отправка буфера в сеть
+// //посылаем на сервер сигнальный байт
+// //25 байт - отправка файла
+// ByteBuf buf = null;//создаем буфер
+// buf = ByteBufAllocator.DEFAULT.directBuffer(1);//задаем размер буфера ()
+// buf.writeByte(signalByte);//записываем в буфер сигнальный байт
+// channel.write(buf);//отправляем на сервер
+//
+// //посылаем на сервер длину имени файла
+// byte[] filenameBytes = path.getFileName().toString().getBytes(StandardCharsets.UTF_8);//создаем байтовый массив с именем файла (получаем из пути имя файла, преобразуем к строке, получаем из нее байты)
+// buf = ByteBufAllocator.DEFAULT.directBuffer(4);//создаем буфер на 4 байта для передачи длины имени файла
+// buf.writeInt(filenameBytes.length);//в буфер кладем int = длине массива с именем файла
+// channel.write(buf);//отправляем не сервер длину имени файла
+//
+// //посылаем на сервер имя файла
+// buf = ByteBufAllocator.DEFAULT.directBuffer(filenameBytes.length);//по длине имени файла выделяем память под буфер
+// buf.writeBytes(filenameBytes);//кладм в буфер имя файла
+// channel.write(buf);//отправляем не сервер имя файла
+//
+// //посылаем на сервер размер файла
+// buf = ByteBufAllocator.DEFAULT.directBuffer(8);//выделяем под буфер 1 long для записи размера файла
+// buf.writeLong(Files.size(path));//записываем в буфер размер файла
+// channel.writeAndFlush(buf);//отправляем на сервер размер файла
+//
+ //отправка файла на сервер
+ ChannelFuture transferOperationFuture = channel.writeAndFlush(region);//отправка файла в сеть
+ if (finishListener != null) {
+ transferOperationFuture.addListener(finishListener);//как только файл передастся сработает finishListener (он может быть, а может и отсутствовать, он приходит в качестве аргумента в метод)
+ }
+ }
+
+ public static void requestFile(Path path, Channel channel, ChannelFutureListener finishListener) throws IOException {
+ //посылаем на сервер сигнальный байт
+ // 26 байт - запрос файла
+ byte[]fileNameBytes = path.getFileName().toString().getBytes(StandardCharsets.UTF_8);
+ ByteBuf buf = ByteBufAllocator.DEFAULT.directBuffer(1+4+fileNameBytes.length);
+ buf.writeByte((byte)26);//сигнальный байт
+ buf.writeInt(fileNameBytes.length);//длина имени файла
+ buf.writeBytes(fileNameBytes);//имя файла
+ channel.writeAndFlush(buf);//отправка на сервер буфера
+ }
+}
+
+
diff --git a/server/pom.xml b/server/pom.xml
index 2eb374c..0844b61 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -16,8 +16,8 @@
org.apache.maven.plugins
maven-compiler-plugin
- 7
- 7
+ 8
+ 8
@@ -35,5 +35,11 @@
1.0-SNAPSHOT
compile
+
+ org.example
+ client
+ 1.0-SNAPSHOT
+ compile
+
\ No newline at end of file
diff --git a/server/src/main/java/MainHandler.java b/server/src/main/java/MainHandler.java
deleted file mode 100644
index 5252d74..0000000
--- a/server/src/main/java/MainHandler.java
+++ /dev/null
@@ -1,31 +0,0 @@
-import io.netty.channel.ChannelHandlerContext;
-
-import io.netty.channel.ChannelInboundHandlerAdapter;
-
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-
-public class MainHandler extends ChannelInboundHandlerAdapter {
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//настройки соединения и FileRequest от клиента
- if (msg instanceof FileRequest) {//если полученое сообщение FileRequest
- FileRequest fr = (FileRequest) msg;//кастует полученное сообщение к FileRequest
- if (Files.exists(Paths.get("server_storage/" + fr.getFilename()))) {//если в server_storage есть файл FileRequest
- FileMessage fm = new FileMessage(Paths.get("server_storage/" + fr.getFilename()));//формирует FileMessage по имени файла из FileRequest
- ctx.writeAndFlush(fm);//отправляет сформированный FileMessage клиенту
- }
- }
- if (msg instanceof FileMessage){
- FileMessage fm = (FileMessage) msg;
- Files.write(Paths.get("server_storage/"
- + fm.getFilename()), fm.getData(), StandardOpenOption.CREATE);
- }
- }
-
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- cause.printStackTrace();
- ctx.close();
- }
-}
diff --git a/server/src/main/java/ProtoHandlerIN.java b/server/src/main/java/ProtoHandlerIN.java
new file mode 100644
index 0000000..67fa541
--- /dev/null
+++ b/server/src/main/java/ProtoHandlerIN.java
@@ -0,0 +1,100 @@
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.nio.file.Paths;
+
+public class ProtoHandlerIN 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: Start file receiving");//сообщаем о старте передачи файла
+ gettingFileNameLength(buf);//получаем длину имени файла
+ byte[] fileName = getFileName(buf);//получаем имя файла
+ System.out.println("STATE: Filename received - " + new String(fileName, "UTF-8"));//собираем из байтового массива строку с именем файла
+ out = new BufferedOutputStream(new FileOutputStream("server_storage/" + new String(fileName)));//открываем BufferedOutputStream для получения данных файла
+ gettingFileLength(buf);//получаем длину файла
+ getFile(buf);//получаем файл
+ } else if (readed == 26) {//пришел сигнальный байт соответствующий запросу файла с сервера
+ gettingFileNameLength(buf);//получаем длину имени запрашиваемого файла
+ String fileName = new String(getFileName(buf));//получаем имя запрашиваемого файла
+ if ((new File("server_storage/"+fileName)).exists()){//если искомый файл существует
+ System.out.println("Искомый файл "+fileName+" существует на сервере");
+ ProtoFileSender.sendFile(Paths.get("server_storage/"+fileName), ctx.channel(), future -> {//указываем файл и сеть для отправки
+ if (!future.isSuccess()) {//действие при неудачной передаче файла
+ future.cause().printStackTrace();
+// Network.getInstance().stop();
+ }
+ if (future.isSuccess()) {//действие при удачной передаче файла
+ System.out.println("Файл "+fileName+" успешно передан");
+// Network.getInstance().stop();
+ }
+ });
+
+ }else {
+ System.out.println("File "+fileName+" not found");
+ }
+ } else {
+ System.out.println("ERROR: Invalid first byte - " + readed);//сообщаем об ошибке (состояние IDEL а сигнальный байт ему не соответствует)
+ }
+ }
+ }
+
+ //получаем длину имени файла
+ private void gettingFileNameLength(ByteBuf buf) {
+ if (buf.readableBytes() >= 4) {//пришло более 4 байт (длина имени файла = 1 int)
+ System.out.println("STATE: 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: 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("File received");
+ out.close();//закрываем файл в который писали байты
+ break;//останавливаем получение
+ }
+// if (buf.readableBytes()==0){buf.release();}
+ }
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+ cause.printStackTrace();
+ ctx.close();
+ }
+}
diff --git a/server/src/main/java/ProtoHandlerOUT.java b/server/src/main/java/ProtoHandlerOUT.java
new file mode 100644
index 0000000..80f2c1c
--- /dev/null
+++ b/server/src/main/java/ProtoHandlerOUT.java
@@ -0,0 +1,2 @@
+public class ProtoHandlerOUT {
+}
diff --git a/server/src/main/java/Server.java b/server/src/main/java/Server.java
index 84e0b7e..1cccf3c 100644
--- a/server/src/main/java/Server.java
+++ b/server/src/main/java/Server.java
@@ -5,35 +5,27 @@
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
-import io.netty.handler.codec.serialization.ClassResolvers;
-import io.netty.handler.codec.serialization.ObjectDecoder;
-
-import io.netty.handler.codec.serialization.ObjectEncoder;
public class Server {
public void run() throws Exception {
- EventLoopGroup mainGroup = new NioEventLoopGroup();
+ EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
- b.group(mainGroup, workerGroup)
+ ServerBootstrap serverBootstrap = b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
- .childHandler(new ChannelInitializer() {
- protected void initChannel(SocketChannel socketChannel) throws Exception {
- socketChannel.pipeline().addLast(
- new ObjectDecoder(50 * 1024 * 1024, ClassResolvers.cacheDisabled(null)),
- new ObjectEncoder(),
- new MainHandler()
- );
+ .childHandler(new ChannelInitializer() { // (4)
+ @Override
+ public void initChannel(SocketChannel ch) throws Exception {
+ ch.pipeline().addLast(new ProtoHandlerIN());
}
});
-
-// .childOption(ChannelOption.SO_KEEPALIVE, true);
- ChannelFuture future = b.bind(8189).sync();
- future.channel().closeFuture().sync();
+ // .childOption(ChannelOption.SO_KEEPALIVE, true);
+ ChannelFuture f = b.bind(8189).sync();
+ f.channel().closeFuture().sync();
} finally {
- mainGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
+ bossGroup.shutdownGracefully();
}
}