javax.websocketclient: как отправить большие двоичные данные из точки клиента в точку обслуживания - PullRequest
0 голосов
/ 01 мая 2020

Я пытаюсь создать клиентское приложение на сервере с помощью Jetty. Я настроил джет-сервер и настроил веб-сокеты. Отправка текстовых сообщений отлично работает между клиентом и сервером. Но как двоичные данные в качестве входного потока могут быть отправлены из конечной точки клиента. Я не могу найти фрагменты, касающиеся клиента websocket. Ниже я попробовал

ServerEndPoint:

   @OnMessage
   public void handleBinaryMessage(InputStream input, Session session) {

       logger.info("onMessage::inputstream");

       try {

        byte[] buffer = new byte[2048];
        try (OutputStream output = session.getBasicRemote().getSendStream())
        {
            int read;
            while ((read = input.read(buffer)) >= 0)
                output.write(buffer, 0, read);
        }

    } catch (IOException e) {
      e.printStackTrace();
    }

ClientEndpoint:

@OnOpen 
public void onOpen(Session s) throws IOException {
  logger.info("Client Connected ... " + s.getId());
  this.session=s;

  session.getBasicRemote().sendText("Ping from client");

  // size of the file 200~500MB
  File source= new File("/tmp/Setup.exe");

  try(InputStream input = new FileInputStream(source)) {


              session.getAsyncRemote().sendObject(input);


            }

}        

Любая помощь приветствуется

РЕДАКТИРОВАТЬ:

Я изменил точку клиента и точку обслуживания. Попытка отправить данные в виде фрагментов, но файл zip частично или иногда даже меньше исходного файла.

размер источника: 1,5 ГБ после записи данных из буфера с использованием потока: 20 КБ

@ ClientEndpoint

   private static void sendFileToRemote(File source) throws FileNotFoundException, IOException {
        // TODO Auto-generated method stub
            Session session=null;
            final WsClient wc = new WsClient("ws://localhost:2714/events/","test");

            session=wc.getSession();

             try (
                        InputStream inputStream = new FileInputStream(source);

                    ) {


                    byte[] chunk = new byte[102400];
                    int chunkLen = 0;
                    while ((chunkLen = inputStream.read(chunk)) != -1) {

                        session.getAsyncRemote().sendBinary(ByteBuffer.wrap(chunk, 0, chunkLen));
                    }

                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }

             }

@ serverendpoint

@ServerEndpoint("/events/")
public class EventListener {
    static Logger logger = Logger.getLogger(Initservice.class.getName());
   private OutputStream os=null; 
@OnOpen
    public void Init(Session session) throws FileNotFoundException {

        this.user_session = session;
        logger.info("onOpen:: server" + session.getId());     

        this.os = new FileOutputStream(new File("/tmp/silicon_test.zip"));
        logger.info("instantiate zip files");

    }

@OnMessage
    public void onMessage(Session session, ByteBuffer byteBuffer) throws IOException {
        try {

          os.write(byteBuffer.get());

        } catch(Exception e) {
            close();
            logger.log(Level.SEVERE,"Exception occured in onMessage :: ", e);
            throw e;
        }
    }
}

1 Ответ

0 голосов
/ 04 мая 2020

Код в вашей ServerEndpoint выглядит так, как будто он должен работать нормально, однако в вашей ClientEndpoint вы отправляете только текстовые данные в ServerEndpoint, и это может быть прочитано только методом onMessage сервера, настроенным для приема текстовых сообщений.

Вместо использования session.getRemoteEndpoint().sendText(...) вы должны использовать метод session.getRemoteEndpoint().sendBinary(...). Это отправит данные в двоичных фреймах вместо текстовых фреймов, и вы сможете получать их на своих серверах handleBinaryMessage методом.

Что касается session.getAsyncRemote().sendObject(input), для выполнения этой работы вам также потребуется предоставьте Encoder.Binary или Encoder.BinaryStream для отправки объекта в виде двоичных данных.

Edit:

WebSocket - это протокол на основе сообщений, и вы отправляете свой данные из файла через несколько сообщений websocket. Вы можете использовать session.getBasicRemote().sendBinary(ByteBuffer, boolean) для отправки частичных сообщений и отправки всех данных в одном сообщении.

Или вы можете попробовать что-то вроде этого кода, который может быть проще.

try (InputStream inputStream = new FileInputStream(source))
{
    try (OutputStream sendStream = session.getBasicRemote().getSendStream())
    {
        inputStream.transferTo(sendStream);
    }
}
...