Привет
Проблема: Я пытаюсь отправить файл клиенту. клиент должен отправить сообщение, когда сообщение получено, сервер должен отправить обратно файл. Я использую аннотированные конечные точки. Я использую реализацию tyrus-standalone-client-1.12.jar на стороне клиента. Серверный код имеет мою спину в виде реализаций tomcat Websocket.
Собственные попытки: Я пробовал простой текст между клиентом и сервером, и он работает. На самом деле, существует множество примеров текстовых сообщений, но вряд ли таких для файлов.
Я прочитал учебники oracle. Я хотел бы что-то простое, как проводка объектов. Я помню, как использовал обычные розетки без особых проблем. Сериализация с одной стороны и десериализация на получающем конце. Но это было долгое время go, и я точно не помню. Просто помните, что это был бриз по сравнению с WebSockets. Я видел, что для отправки объектов нужны декодеры и кодеры, но примеров нет. В основном учебник добавляет:
//your code goes here
Я видел примеры того, «какой код идет туда», но они, как правило, просто текст. поэтому я бросил это. Так как это файл, я думаю, мне нужно отправить в байтах. Но меня смущает, что нужно отправить ByteBuffer, а вы можете получить как ByteBuffer, так и byte []. Поскольку задействованы ByteBuffers, я где-то прочитал о FileChannel как полезную вещь для чтения файла со стороны сервера, а затем отправил ByteBuffers, который он возвращает различными методами. Я боролся, потому что
Использовал FileChannel.lock () НЕ то, что ожидал. Он считал, что он заблокировал файлы, чтобы другие потоки не могли связываться с файлом во время чтения, поэтому остальная часть кода не запускалась. Это только казалось, чтобы заблокировать. После удаления снова заработало.
- На приемном конце я обнаружил, что 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.