javax.websocketclient : 如何将大型二进制数据从客户端发送到服务器端
javax.websocketclient : how to send large binary data from clientendpoint to serverendpoint
我正在尝试使用码头构建服务器客户端应用程序。我已经设置了一个码头服务器并配置了 websockets。发送短信在客户端和服务器之间工作正常。但是如何从客户端发送二进制数据作为输入流。我找不到关于 websocket 客户端的任何片段。以下是我尝试过的
服务器端点:
@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;
}
}
}
ServerEndpoint 中的代码看起来应该可以正常工作,但是在 ClientEndpoint 中,您仅向 ServerEndpoint 发送文本数据,并且这只能由配置为接收文本消息的服务器 onMessage 方法读取。
您应该使用方法 session.getRemoteEndpoint().sendBinary(...)
,而不是使用 session.getRemoteEndpoint().sendText(...)
。这将以二进制帧而不是文本帧的形式发送数据,您将能够在您的服务器 handleBinaryMessage
方法中接收它。
至于 session.getAsyncRemote().sendObject(input)
,要完成这项工作,您还需要提供 Encoder.Binary
或 Encoder.BinaryStream
以便将对象作为二进制数据发送。
编辑:
WebSocket 是一种基于消息的协议,您通过多个 websocket 消息从文件发送数据。您可以使用 session.getBasicRemote().sendBinary(ByteBuffer, boolean)
发送部分消息并在同一消息中发送所有数据。
或者您可以尝试类似这样的代码,它可能更简单。
try (InputStream inputStream = new FileInputStream(source))
{
try (OutputStream sendStream = session.getBasicRemote().getSendStream())
{
inputStream.transferTo(sendStream);
}
}
我正在尝试使用码头构建服务器客户端应用程序。我已经设置了一个码头服务器并配置了 websockets。发送短信在客户端和服务器之间工作正常。但是如何从客户端发送二进制数据作为输入流。我找不到关于 websocket 客户端的任何片段。以下是我尝试过的
服务器端点:
@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;
}
}
}
ServerEndpoint 中的代码看起来应该可以正常工作,但是在 ClientEndpoint 中,您仅向 ServerEndpoint 发送文本数据,并且这只能由配置为接收文本消息的服务器 onMessage 方法读取。
您应该使用方法 session.getRemoteEndpoint().sendBinary(...)
,而不是使用 session.getRemoteEndpoint().sendText(...)
。这将以二进制帧而不是文本帧的形式发送数据,您将能够在您的服务器 handleBinaryMessage
方法中接收它。
至于 session.getAsyncRemote().sendObject(input)
,要完成这项工作,您还需要提供 Encoder.Binary
或 Encoder.BinaryStream
以便将对象作为二进制数据发送。
编辑:
WebSocket 是一种基于消息的协议,您通过多个 websocket 消息从文件发送数据。您可以使用 session.getBasicRemote().sendBinary(ByteBuffer, boolean)
发送部分消息并在同一消息中发送所有数据。
或者您可以尝试类似这样的代码,它可能更简单。
try (InputStream inputStream = new FileInputStream(source))
{
try (OutputStream sendStream = session.getBasicRemote().getSendStream())
{
inputStream.transferTo(sendStream);
}
}