Невозможно отправить весь файл через WebSocket - PullRequest
0 голосов
/ 12 марта 2020

Привет

Проблема: Я пытаюсь отправить файл клиенту. клиент должен отправить сообщение, когда сообщение получено, сервер должен отправить обратно файл. Я использую аннотированные конечные точки. Я использую реализацию tyrus-standalone-client-1.12.jar на стороне клиента. Серверный код имеет мою спину в виде реализаций tomcat Websocket.

Собственные попытки: Я пробовал простой текст между клиентом и сервером, и он работает. На самом деле, существует множество примеров текстовых сообщений, но вряд ли таких для файлов.

Я прочитал учебники oracle. Я хотел бы что-то простое, как проводка объектов. Я помню, как использовал обычные розетки без особых проблем. Сериализация с одной стороны и десериализация на получающем конце. Но это было долгое время go, и я точно не помню. Просто помните, что это был бриз по сравнению с WebSockets. Я видел, что для отправки объектов нужны декодеры и кодеры, но примеров нет. В основном учебник добавляет:

//your code goes here

Я видел примеры того, «какой код идет туда», но они, как правило, просто текст. поэтому я бросил это. Так как это файл, я думаю, мне нужно отправить в байтах. Но меня смущает, что нужно отправить ByteBuffer, а вы можете получить как ByteBuffer, так и byte []. Поскольку задействованы ByteBuffers, я где-то прочитал о FileChannel как полезную вещь для чтения файла со стороны сервера, а затем отправил ByteBuffers, который он возвращает различными методами. Я боролся, потому что

  1. Использовал FileChannel.lock () НЕ то, что ожидал. Он считал, что он заблокировал файлы, чтобы другие потоки не могли связываться с файлом во время чтения, поэтому остальная часть кода не запускалась. Это только казалось, чтобы заблокировать. После удаления снова заработало.

  2. На приемном конце я обнаружил, что backingArray может просто исчезнуть ByteBuffer «теряет» резервный массив при отправке через WebSockets . Затем я нашел этот метод "get (byte [] arr)". Но так как у ByteBuffer нет метода .size (), я не знал, насколько большим должен быть массив получения. В конце концов я обнаружил, что могу использовать .hasRemaining () для управления чтением al oop из ByteBuffer.

Так как я был настолько раздражен ByteBuffers и его странным интерфейсом, я посмотрел в другом месте. Кроме того, он просто не работал при его использовании, и я знаю, что это связано с моим отсутствием знаний;). Тем не менее. Наконец я нашел эту ссылку https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/BinaryWebSocket/binaryWebSocket.html Это был не просто текст, а фактически изображение: -o. СМИ! Что-то, что должно быть отправлено в двоичном виде, верно? Поэтому я основал свой код на этом. И сделал несколько настроек здесь и там. В основном это, кажется, часть получения, которую я не знаю, как реализовать. Но я покажу деловую часть отправляющей и получающей части.

Отправляющая часть:

import java.io.IOException;
import java.net.SocketException;

import javax.websocket.EndpointConfig;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import se.microbusgroup.helpers.FileSender;

@ServerEndpoint("/echo")
public class Contact {
    private Session session;

    @OnMessage
    public void onMessage(Session session, String msg) {
            System.out.println("Im answering");
            try {
                session.getBasicRemote().sendText("hmmm");
            }

            catch(IOException e) {
                System.out.println("client prolly disconnected.");
            }
            if(msg.equals("moviePlease")) {
                FileSender mvsender = new FileSender(session);
                mvsender.send("file:///C:/Users/Username/Desktop/video.mp4");
            }       

    }

    @OnOpen
    public void onOpen(Session session, EndpointConfig conf) {
        session.getAsyncRemote().sendText("Welcome!");
        this.session = session;
    }

    @OnError
    public void onError(Session session, Throwable t) {
        String str = t.getMessage();
        System.out.println("Something went wrong so I closed the connection.: " + str);
    }

}

Принимающая часть:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.util.ArrayList;

import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.MessageHandler;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;

@ClientEndpoint
public class WebsocketThing {
    private Session session;
    private MessageHandler messHandler;
    private ArrayList<Byte> listOfBytes = new ArrayList<>();    

    public WebsocketThing(URI uri) {
        try {
            WebSocketContainer container = ContainerProvider.getWebSocketContainer();
            container.connectToServer(this, uri);
        } 
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    @OnOpen 
    public void onOpen(Session session) {
        this.session = session;
        System.out.println("You have connected!");
    }
    @OnClose
    public void onClose(Session session, CloseReason reason) {
        this.session = null;
        System.out.println("You have disconnected.");
    }

    @OnMessage
    public void gettingMovie(InputStream input) {

        try {
            URI uriOut = new URI("file:///C://Users/Username/arrivedfile.mp4");
            File fileOut = new File(uriOut);
            fileOut.createNewFile();
            int read;
            OutputStream output = new FileOutputStream(fileOut);
            byte[] buffer = new byte[1];
            while ((read = input.read(buffer)) > 0) {
                  output.write(buffer, 0, read);
                }
        } catch (URISyntaxException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public void send(String message) {
        session.getAsyncRemote().sendText(message);
    }

}

Ожидаемое поведение:

Весь файл до конца, куда клиент указывает, даже большие файлы, и возможность проигрывать его с видео.

Фактическое поведение: Отправляет часть файла, более половины фактически. Но всегда кажется, что в конце концов не хватает. Не в состоянии играть в нее. Иногда не хватает больше, иногда меньше. перепробованы несколько файлов MegaBytes.

...