【问题标题】:javax.websocketclient : how to send large binary data from clientendpoint to serverendpointjavax.websocketclient:如何将大型二进制数据从客户端发送到服务器端
【发布时间】:2020-08-16 08:28:11
【问题描述】:

我正在尝试使用码头构建服务器客户端应用程序。我已经设置了一个码头服务器并配置了 websockets。在客户端和服务器之间发送短信工作正常。但是如何从客户端端点发送二进制数据作为输入流。我找不到任何关于 websocket 客户端的 sn-ps。以下是我尝试过的

服务器端点:

   @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();
    }

客户端端点:

@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);


            }

}        

感谢任何帮助

编辑:

我修改了clientendpoint和serverendpoint。尝试以块的形式发送数据,但 zip 文件是部分文件,有时甚至比源文件小。

源大小:1.5gb 使用流从缓冲区写入数据后:20kb

@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;
        }
    }
}

【问题讨论】:

    标签: java websocket jetty java-websocket jsr356


    【解决方案1】:

    您的 ServerEndpoint 中的代码看起来应该可以正常工作,但是在您的 ClientEndpoint 中,您只向 ServerEndpoint 发送文本数据,并且只能由配置为接收文本消息的服务器 onMessage 方法读取。

    您应该使用方法session.getRemoteEndpoint().sendBinary(...),而不是使用session.getRemoteEndpoint().sendText(...)。这将以二进制帧而不是文本帧的形式发送数据,您将能够在您的服务器中接收它handleBinaryMessage 方法。

    至于session.getAsyncRemote().sendObject(input),要完成这项工作,您还需要提供Encoder.BinaryEncoder.BinaryStream 以便将对象作为二进制数据发送。

    编辑:

    WebSocket 是一个基于消息的协议,您通过多个 websocket 消息从文件中发送数据。您可以使用session.getBasicRemote().sendBinary(ByteBuffer, boolean) 发送部分消息并在同一消息中发送所有数据。

    或者您可以尝试类似这样的代码,它可能更简单。

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

    【讨论】:

    • 感谢您的青睐。我尝试将数据作为块发送,这次我在 serverendpoint 中得到了响应,但数据是部分的,甚至非常小。我在帖子中提到了变化
    • 我已经更新了答案,添加了一些关于在同一个 websocket 消息中发送数据的附加信息。
    • 非常感谢@Lachlan。我已将文件作为块传输。但仍然对 session.getBasicRemote().getSendStream() 感到困惑。如果我在我的 serverEndPoint 使用它。文件将保存在哪里?可能在当前目录?
    • 发送流将数据作为 websocket 消息发送到另一个 websocket 端点,而不是将其保存到文件中,您将在客户端使用它来发送文件。阅读 javadoc。如果您想写入文件,您仍然可以使用您正在使用的 FileOutputStream。
    猜你喜欢
    • 2017-02-16
    • 2014-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    • 2021-12-07
    • 2017-10-17
    相关资源
    最近更新 更多