Я пишу базовое приложение для передачи файлов. Он использует сокеты TCP и входные потоки. Идея состоит в том, что приложение открывает и клиент, и сервер в разных потоках, поэтому оно похоже на одноранговое приложение. Я борюсь с обменом сообщениями и файлами между хостами. Я отправляю файлы через тот же поток, который использую для отправки массивов файлов byte []. В идеале это приложение будет отправлять контрольную сумму файлов и переподключаться при нарушении соединения, однако я не знаю, как это реализовать. Я не могу решить это с 2 недель, кто-нибудь знает, как я могу решить это?
MyServer.class
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServer implements Runnable{
private String server;
private int port;
public MyServer(String server, int port){
this.server = server;
this.port = port;
}
@Override
public void run() {
while (true) {
try (
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(
clientSocket.getOutputStream(), true
);
DataOutputStream dos = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()))
) {
String inputLine, outputLine;
System.err.println("Port used " + clientSocket.getPort());
if(clientSocket.isClosed()){
Socket dwa = serverSocket.accept();
}
//exchange messages
MyServerProtocol mServPrtcl = new MyServerProtocol();
outputLine = mServPrtcl.processInput(null);
out.println(outputLine);
while ((inputLine = in.readLine()) != null) {
if (inputLine.startsWith("FILE_TOSERVER")) { //file is sent to server
DataInputStream din = new DataInputStream(clientSocket.getInputStream());
String newFileName = inputLine.substring(13);
FilePuller puller = new FilePuller(din);
puller.pullFile(newFileName);
continue;
} else {
outputLine = mServPrtcl.processInput(inputLine);
}
if(inputLine.startsWith("WAIT") || outputLine.equals("WAIT")){
out.println("WAITING");
}
if (outputLine.startsWith("SEND_FILE")) {
int fileNumber = Integer.parseInt(outputLine.substring(9));
out.println("FILE_DOWNLOAD" + mServPrtcl.getFileName(fileNumber));
byte[] bytesToSend = mServPrtcl.getFileByteArray(fileNumber);
FilePusher pusher = new FilePusher(dos);
pusher.pushFile(bytesToSend);
out.println("Przeslano plik, wpisz cokolwiek by kontynuować...");
} else if (outputLine.startsWith("GET_FILE")) {
out.println("FILE_UPLOAD");
}else{
out.println(outputLine);
}
}
} catch (IOException e) {
System.out.println("Port unavailable: " + port + ", Host: " + server + "\n" + "Changing to " + (port + 1));
port++;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Client.class
import java.io.*;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;
public class Client implements Runnable {
private String hostname;
private int port;
public Client(String hostname, int port){
this.hostname = hostname;
this.port = port;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(4800);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Socket socket = new Socket(hostname, port);
//read thread
new Thread(() -> {
String serverInput;
MyFilesManager flsMng = new MyFilesManager(Main.getAppFilesPath());
flsMng.fetchFiles();
try (
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
PrintWriter readThreadOut = new PrintWriter(socket.getOutputStream(), true)
){
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader readReader = new BufferedReader(new InputStreamReader(System.in));
while ((serverInput = in.readLine()) != null) {
if(serverInput.startsWith("FILE_DOWNLOAD")){
String fileName = serverInput.substring(13);
DataInputStream dis = new DataInputStream(socket.getInputStream());
FilePuller puller = new FilePuller(dis);
puller.pullFile(fileName);
}else if(serverInput.startsWith("FILE_UPLOAD")){
readThreadOut.println("WAIT");
new Thread(() -> {
Scanner scanner = new Scanner(System.in);
System.out.println("Which file do you want to push?");
MyFilesManager fileManager = new MyFilesManager(Main.getAppFilesPath());
System.out.println(fileManager.displayFiles());
String fileNo = null;
fileNo = scanner.nextLine();
int myFileNumber = Integer.parseInt(fileNo);
readThreadOut.println("FILE_TOSERVER" + fileManager.getFileName(myFileNumber));
byte[] toSend;
try {
toSend = fileManager.getFileByteArray(myFileNumber);
FilePusher pusher = new FilePusher(dos);
pusher.pushFile(toSend);
} catch (IOException e) {
e.printStackTrace();
}
readThreadOut.println("FILE_SENT");
}).start();
}else if(serverInput.equals("WAITING")){
readThreadOut.println("WAIT");
}
else{
System.out.println("Server message: " + serverInput);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
//reading thread
new Thread(() -> {
String userInput;
try {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while ((userInput = reader.readLine()) != null) {
out.println(userInput);
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
break;
} catch (SocketException se){
} catch (IOException e) {
System.err.println("Client is unable to connect");
}
}
}
}
Передача файлов (Пуллер)
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class FilePuller {
private DataInputStream dis;
public FilePuller(DataInputStream dis){
this.dis = dis;
}
public void pullFile(String fileName) throws IOException {
File f = new File(Main.getAppFilesPath() + "received_" + fileName);
FileOutputStream fos = new FileOutputStream(f);
int length = dis.readInt(); // read "size" of file
if(length > 0) {
byte[] message = new byte[length];
dis.readFully(message);
fos.write(message);
}
fos.close();
}
}
Передача файлов (Pusher)
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class FilePusher {
private DataOutputStream dos;
public FilePusher(DataOutputStream outputStream){
this.dos = outputStream;
}
public void pushFile(byte[] bytes) throws IOException {
try {
dos.writeInt(bytes.length); // send file "size"
dos.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}