Java TCP Sockets - проблема обмена файлами и чата с потоками - PullRequest
0 голосов
/ 06 января 2019

Я пишу базовое приложение для передачи файлов. Он использует сокеты 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();
        }
    }


}
...