powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Добавить многопоточность в приложение
7 сообщений из 7, страница 1 из 1
Добавить многопоточность в приложение
    #39258345
archelite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый вечер всем

есть такое задание

Создать приложения сервера и клиента для передачи файлов.
Сервер должен уметь обслуживать одновременно несколько клиентов.
Запросы обслуживаемые сервером:
Отправить список доступных файлов (из одной заданной при старте сервера директории).
Отправить содержимое запрошенного файла.
Сервер также собирает статистику (количество скачиваний каждого файла) и каждые N секунд сохраняет статистику в текстовом формате в файл.

Клиент при подключении выдает приглашение пользователю на ввод команды, возможные команды:
Запрос списка доступных файлов.
Скачать один файл и сохранить его локально.
Завершить сессию.
После выполнения запросов 1 или 2 клиент ожидает новой команды от пользователя.
Интерфейс пользователя: консоль. Предусмотреть логгирование в файл информации о происходящих процессах. Предусмотреть безопасную остановку сервера.

функционал уже весь реализован, осталось правильно распределить по потокам.
Я пока предполагаю для сервера:
создавать поток для обработки команд от 1 юзера, по принципу 1 юзер - 1 поток.
поток для записи статистики
поток который принимает команды из консоли (для возможности остановки сервера)

Либо лучше наверно будет создать поток для каждого метода, взаимодействующего с клиентами?
Потому что в первом случае если юзеры отправят команду одновременно, ресурс может быть занят и будет ошибка

Для клиента должно хватить консольного потока считывающего команды/получающего ответ + потока пишущего логи.

Еще сейчас обмен данными между сервером и клиентами идет посредством строк, что не есть гуд, в результате программа может передавать только мелкие текстовые файлы, какие потоки лучше использовать для полноценной передачи и записи файлов?

сам гавнокод)
Сервер
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
public class Server_app {

    private final int port = 12345;
    private ServerSocket serverSocket;
    private Socket socket;
    private InputStream in;
    private OutputStream out;
    private FileInputStream fileReader;
    private DataInputStream inData;
    private DataOutputStream outData;
    private String[] fileList;
    private final Map<String, Integer> downloadStats = new TreeMap<>();
    private final File serverFolder = new File("C:\\testdir");
    private File[] serverFiles;
    private String command;
    private String fileContent;
    private List<String> log = new ArrayList<>();
    private int n;
    private FileWriter logWriter;
    private FileWriter statsWriter;

    public static void main(String[] args) {
        Server_app s = new Server_app();
        s.runServer();
        s.fillFileList();
        s.setDownloadCounters();
        s.recieveCommands();
    }

    public void runServer() {
        try {
            serverSocket = new ServerSocket(port);
            message("Server started");
            message("to stop the server you can use -exit command \n");
        } catch (IOException ex) {
            message(ex.getMessage());
        }
    }

    public void fillFileList() {
        if (serverFolder.exists() && serverFolder.isDirectory() && serverFolder.canRead()) {
            fileList = serverFolder.list();
        }
    }

    public void setDownloadCounters() {
        for (String fileName : fileList) {
            downloadStats.put(fileName, 0);
        }
    }

    public void increaseDownloadCounters(String fileName) {
        for (Map.Entry<String, Integer> entry : downloadStats.entrySet()) {
            if (entry.getKey().equals(fileName)) {
                int tmp = entry.getValue();
                entry.setValue(++tmp);
            }
        }
    }

    public void recieveCommands() {
        try {
            while (true) {
                socket = serverSocket.accept();
                in = socket.getInputStream();
                out = socket.getOutputStream();
                inData = new DataInputStream(in);
                outData = new DataOutputStream(out);
                message("Got a connection from " + socket.getInetAddress() + ":" + socket.getPort());
                command = inData.readUTF();
                if (command.equals("-getFilesList")) {
                    message("Recieved command: " + command + " from: " + socket.getInetAddress() + ":" + socket.getPort());
                    sendFileList();
                    message("FileList was sended to " + socket.getInetAddress() + ":" + socket.getPort());
                }
                if (command.contains("-download ")) {
                    boolean b = false;
                    for (String fileName : fileList) {                       
                        if (command.contains(fileName)) {
                            b = true;
                            message("Recieved command: " + command + " from: " + socket.getInetAddress() + ":" + socket.getPort());
                            sendFile();
                            message("File was sended to " + socket.getInetAddress() + ":" + socket.getPort());
                        }
                    }
                    if (b==false){
                      outData.writeUTF("File not found on server, check filelist");
                      outData.writeUTF("File not found on server, check filelist");
                      message("File not found on server, check filelist");
                    }
                }
                if (!command.equals("-getFilesList") && !command.contains("-download ")) {
                    outData.writeUTF("Unknown command \"" + command + "\"");
                    outData.writeUTF("Unknown command \"" + command + "\"");
                    message("Unknown command \"" + command + "\"" + " from " + socket.getInetAddress() + ":" + socket.getPort());
                }
            }
        } catch (IOException ex) {
            message(ex.getMessage());
        }
    }

    public void sendFileList() throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("FileList:").append("\n");
        for (String fileName : fileList) {
            sb.append(fileName).append("\n");
        }
        outData.writeUTF(sb.toString());
    }

    public void sendFile() throws IOException {
        writeLogFile();
        serverFiles = serverFolder.listFiles();
        for (File serverFile : serverFiles) {
            if (command.contains(serverFile.getName())) {
                outData.writeUTF(command);
                fileReader = new FileInputStream(new File(serverFile.getAbsolutePath()));
                byte[] buffer = new byte[fileReader.available()];
                while (fileReader.available() > 0) {
                    n = fileReader.read(buffer);
                }
                fileContent = new String(buffer, 0, n);
                outData.writeUTF(fileContent);
                increaseDownloadCounters(serverFile.getName());
                writeStatistics();
            } 
        }
    }

    public void writeLogFile() {
        try {
            int x = 0;
            logWriter = new FileWriter(serverFolder + "\\server_log.txt", true);
            for (String logMessage : log) {
                logWriter.write(logMessage);
                logWriter.write(System.getProperty("line.separator"));
                ++x;
                if (x == 2) {
                    logWriter.write(System.getProperty("line.separator"));
                }
            }
            logWriter.close();
        } catch (IOException ex) {
            message(ex.getMessage());
        }
    }

    public void writeStatistics() {
        try {
            statsWriter = new FileWriter(serverFolder + "\\download_stats.txt");
            for (Map.Entry<String, Integer> entry : downloadStats.entrySet()) {
                statsWriter.write(entry.getKey() + " downloads: " + entry.getValue());
                statsWriter.write(System.getProperty("line.separator"));
            }
            statsWriter.close();
        } catch (IOException ex) {
            message(ex.getMessage());
        }
    }

    public void serverShutdown() {
        BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            try {
                String s = r.readLine();
                if (s.equals("-exit")) {
                    in.close();
                    out.close();
                    inData.close();
                    outData.close();
                    socket.close();
                    serverSocket.close();
                    message("Server shutdown");
                }
            } catch (IOException ex) {
                message(ex.getMessage());
            }
        }
    }

    public void message(String msg) {
        System.out.println(msg);
        log.add(msg);
    }
}



Клиент
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
public class Client_App {

    private String strAddress = "127.0.0.1";
    private int port = 12345;
    private InputStream in;
    private OutputStream out;
    private DataInputStream inData;
    private DataOutputStream outData;
    private DataOutputStream fileData;
    private InetAddress ipAddress;
    private Socket socket;
    private String response;
    private String fileContent;
    private FileOutputStream fileWriter;
    private final File outputDir = new File("C:\\downloads");
    private String[] recievedFileName;
    private List<String> log = new ArrayList<>();
    private FileWriter logWriter;

    public static void main(String[] args) {
        Client_App client_App = new Client_App();
        client_App.runClient();
        client_App.sendCommands();
    }

    public void runClient() {
        try {
            ipAddress = InetAddress.getByName(strAddress);
            socket = new Socket(ipAddress, port);
            in = socket.getInputStream();
            out = socket.getOutputStream();
            inData = new DataInputStream(in);
            outData = new DataOutputStream(out);
            message("Client started");
            message("You can enter the following commands: ");
            message("-getFilesList");
            message("-download %file_name.file_extension%");
            message("-exit \n ");
        } catch (UnknownHostException ex) {
            message(ex.getMessage());
        } catch (IOException ex) {
            message(ex.getMessage());
        }
    }

    public void sendCommands() {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            try {
                String s = reader.readLine();
                if (s.equals("-exit")) {
                    in.close();
                    out.close();
                    inData.close();
                    outData.close();
                    socket.close();
                    message("Client shutdown");
                    break;
                }
                if (s.equals("-getFilesList")) {
                    outData.writeUTF(s);
                    response = inData.readUTF();
                    recieveResponse(response);
                } else {
                    outData.writeUTF(s);
                    response = inData.readUTF();
                    fileContent = inData.readUTF();
                    if (response.equals(fileContent)) {
                        message(response);
                    } else {
                        recieveResponse(response, fileContent);
                    }
                }
            } catch (IOException ex) {
                message(ex.getMessage());
            }
        }
    }

    public void recieveResponse(String fileName) {
        if (response.contains("FileList:")) {
            recieveFileList();
        } else {
            message(response);
        }
    }

    public void recieveResponse(String fileName, String fileContent) {
        recievedFileName = response.split("-download ");
        recieveFile(recievedFileName[1]);
    }

    public void recieveFileList() {
        message(response);
    }

    public void recieveFile(String recievedfileName) {
        if (outputDir.exists() && outputDir.isDirectory() && outputDir.canWrite()) {
            writeDownloadedFile(recievedfileName);
            message(recievedfileName + " was downloaded in existing directory");
            writeLogFile();
        } else if (!outputDir.exists()) {
            outputDir.mkdir();
            writeDownloadedFile(recievedfileName);
            message(recievedfileName + " was downloaded in new directory");
        }
    }

    public void writeDownloadedFile(String recievedfileName) {
        try {
            fileWriter = new FileOutputStream(new File(outputDir + "\\" + recievedfileName));
            fileData = new DataOutputStream(fileWriter);
            fileData.writeUTF(fileContent);
            fileWriter.close();
            fileData.close();
        } catch (IOException ex) {
            message(ex.getMessage());
        }
    }

    public void message(String msg) {
        System.out.println(msg);
        log.add(msg);
    }

    public void writeLogFile() {
        try {
            int x = 0;
            logWriter = new FileWriter(outputDir + "\\client_log.txt");
            for (String logMessage : log) {
                logWriter.write(logMessage);
                logWriter.write(System.getProperty("line.separator"));
                ++x;
                if (x == 5) {
                    logWriter.write(System.getProperty("line.separator"));
                }
            }
            logWriter.close();
        } catch (IOException ex) {
            message(ex.getMessage());
        }
    }
}
...
Рейтинг: 0 / 0
Добавить многопоточность в приложение
    #39258548
archelite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
с потоками разобрался, всё работает как надо, правда пересылать можно только текстовые файлы не больше 64кб)
Хотелось бы сделать более универсально.

в этом куске кода из файла получается массив байтов на стороне сервера
Код: java
1.
2.
3.
4.
5.
fileReader = new FileInputStream(new File(serverFile.getAbsolutePath()));
                byte[] buffer = new byte[fileReader.available()];
                while (fileReader.available() > 0) {
                    fileReader.read(buffer);                   
                }



массив не пустой, байты там есть, если передавать их строкой всё ок, а если так
Код: java
1.
outData.write(buffer);

то возможно что нет.

здесь на стороне клиента пытаемся читать входящий поток в байтовый массив, но он по какой-то причине остается пуст
Код: java
1.
2.
      buffer = new byte[inData.available()];
                    inData.readFully(buffer);


где может быть проблема?
...
Рейтинг: 0 / 0
Добавить многопоточность в приложение
    #39258647
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
archeliteгде может быть проблема?
Как минимум проблема в том, что нужно придумать некий заголовок, исходящий от сервера перед отправкой, где указывать полный размер файла и, например, его имя.
Клиент должен знать, что и сколько ему придет. Это решит проблему размера и типа файлов (только текстовые).
...
Рейтинг: 0 / 0
Добавить многопоточность в приложение
    #39259107
archelite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
wadman, заголовок есть, при отправке файла с сервера отправляется строкой заголовок + байтовый массив по размеру файла.
Размер файл получает при чтении из директории сервера.

Если писать файлы не строками, а через байтовый массив, то получается что клиент создает и записывает файл в нужном формате и с нужным заголовокм, но он пустой, весит 0 байт, содержимое где-то пропадает.

Буду очень благодарен если покажете пример кода с клиент-сервером, где передаются файлы через байтовый буффер.
...
Рейтинг: 0 / 0
Добавить многопоточность в приложение
    #39259118
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
archelite
Код: java
1.
2.
3.
4.
5.
fileReader = new FileInputStream(new File(serverFile.getAbsolutePath()));
                byte[] buffer = new byte[fileReader.available()];
                while (fileReader.available() > 0) {
                    fileReader.read(buffer);                   
                }



Код: java
1.
2.
      buffer = new byte[inData.available()];
                    inData.readFully(buffer);




Не корректное использование ф-ции available(). Они совсем другое делает / возвращает.

AFAIK

wadmanКак минимум проблема в том, что нужно придумать некий заголовок, исходящий от сервера перед отправкой, где указывать полный размер файла и, например, его имя.
Клиент должен знать, что и сколько ему придет. Это решит проблему размера и типа файлов (только текстовые).
+1
...
Рейтинг: 0 / 0
Добавить многопоточность в приложение
    #39259192
archelite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Leonid Kudryavtsev, большое спасибо, исправил, только есть проблема с кодировкой в некоторых файлах, если например передаю картинки или некоторые документы, принятые файлы не открывает, пишет что файл поврежден, хотя размер, имя, формат - всё совпадает до байта
...
Рейтинг: 0 / 0
Добавить многопоточность в приложение
    #39259255
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут странно как-то. С кодировками.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
outData.writeUTF(command);
                fileReader = new FileInputStream(new File(serverFile.getAbsolutePath()));
                byte[] buffer = new byte[fileReader.available()];
                while (fileReader.available() > 0) {
                    n = fileReader.read(buffer);
                }
                fileContent = new String(buffer, 0, n);
                outData.writeUTF(fileContent);
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Добавить многопоточность в приложение
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]