Задать вопрос
Meridian312
@Meridian312

Как можно связать файл-поток от двух клиентов для передачи одного файла?

Сначало расскажу, что я хочу сделать, я студент и пишу курсовую по Java.

Есть клиент A и B, есть сервер S.

- Клиент A отправляет файл (открывает поток FileInputStream к файлу N и передаёт это потоку OutputStream сервера S).
- Клиент B знает об этом и получает поток вида FileInputStream файла от клиента A и пишет его при помощи FileOutputStream к себе на диск)

Возможна ли прямая передача через потоки, где сервер является только связывающим звеном двух потоков (принимающим и отдающим), которое не производит передачи, а вся передача происходит принимающей стороной (клиентов B)?

Если это невозможно, то получается единственный способ это сначало позволить клиенту A загрузить на сервер файл и затем оповестить клиента B о том, что он может его теперь скачать с сервера (не у явного клиента)

Последнее решение немного смущает, из-за того, что лично хочеться достигнуть стриминга между клиентами, а не залил-отдал, просто ещё немного не понимаю как к этому подойти.

PS: Передача файла будет проводиться через RMI Java. На данный момент я могу загружать файл и скачивать с сервера, я могу сделать следующее, Клиент А залил на сервер, клиент B скачал с сервера.

Часть решения я вижу в ostermiller.org/convert_java_outputstream_inputstr... нужны объяснения как.

Реализовал, я последнюю передачу, так:

1. Клиент имеет менеджер
public class FileTransferManager {

    private int BUFFER_SIZE = 1024 * 64;
    private FileTransferRemote refService;

    public FileTransferManager(String host, String serviceName) throws NotBoundException,
            MalformedURLException, RemoteException {
        refService =
                (FileTransferRemote) Naming.lookup("rmi://" + host + "/" + serviceName);
    }

    public FileTransferRemote getRefService() {
        return refService;
    }

    public void copy(InputStream in, OutputStream out) throws IOException {
        byte[] b = new byte[BUFFER_SIZE];
        int len;
        while ((len = in.read(b)) >= 0) {
            out.write(b, 0, len);
        }
        in.close();
        out.close();
    }

    public void upload(File src, File dest) throws IOException {
        copy(new FileInputStream(src), refService.getOutputStream(dest));
    }

    public void download(File src, File dest) throws IOException {
        copy(refService.getInputStream(src), new FileOutputStream(dest));
    }
}


2. Это интерфейс сервиса для передачи файлов (серверная)
// Интерфейс
public interface FileTransferRemote extends Remote {

    public InputStream getInputStream(File f) throws IOException;

    public OutputStream getOutputStream(File f) throws IOException;

    public String method() throws RemoteException;
}

// Имплементация сервиса
public class FileTransfer extends AbstractService
        implements FileTransferRemote {

    public FileTransfer(int port, String name) throws RemoteException {
        super(port, name);
    }

    @Override
    public String method() throws RemoteException {
        return this.getClass().getName();
    }

    @Override
    public OutputStream getOutputStream(File f) throws IOException {
        return new OutputStreamTransferable(
                new FileOutputStreamHandler(new FileOutputStream(f)));
    }

    @Override
    public InputStream getInputStream(File f) throws IOException {
        // Каждый файл обёртывается в Remote Object File(In|Out)putStreamHandler, который описывает файл
        // Дальше каждый File(In|Out)putStreamHandler заворачивается в Serializable File(In|Out)putStreamTransferable объект
        // Дальше этот (In|Out)putStreamTransferable летит через сеть
        return new InputStreamTransferable(
                new FileInputStreamHandler(new FileInputStream(f)));
    }
}
  • Вопрос задан
  • 2875 просмотров
Подписаться 3 Оценить 2 комментария
Пригласить эксперта
Ответы на вопрос 1
leahch
@leahch
3D специалист. Dолго, Dорого, Dерьмово.
Рекомендую поступить по другому. Работать не через файлы/потоки, а через сообщения. А для этого использовать очереди на основе amqp, например на основе rabbitmq. Тогда задача преобразуется в следующую: сервер и клиент В подписан на очередь, куда пушит сообщениями клиент А.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы