Определить общий размер сообщения CoAP
У меня есть и сервер CoAP, и клиент, который я написал на Java с библиотекой Californium. Я могу получать ресурсы с сервера как через клиента, так и через Firefox с расширением Copper (Cu). Я хочу получить общий размер ответа от сервера. Я уже могу получить размер полезной нагрузки, но мне нужен общий размер сообщения. Неважно, если я сделаю это с помощью кода или с помощью инструмента. До сих пор я не смог найти в Google способ сделать это.
1 ответ
Это зависит от того, что вы хотите получить.
1) Если вы просто хотите обнаружить некоторые следы.
Я бы рекомендовал использовать wireshark, захватывать и анализировать пакеты:
2) Если вы хотите использовать длины программно
Насколько я знаю, нет чистого и прямого способа добиться этого.
Есть некоторые обходные пути.
соединитель
Вы можете обернуть Connector и явно установить конечную точку для клиента (и сервера тоже, но я показываю версию клиента):
CoapClient client = new CoapClient(new URI(uri));
client.setEndpoint(
new CoapEndpoint(
new InterceptingUDPConnector(
new UDPConnector(
new InetSocketAddress(
portNumber
)
)
),
NetworkConfig.getStandard()
)
)
Вот обертка разъема:
public class InterceptingUDPConnector implements Connector {
private final Connector origin;
public InterceptingUDPConnector(Connector origin) {
this.origin = origin;
}
@Override
public void send(RawData msg) {
System.out.println("Length:" + msg.getSize());
origin.send(msg);
}
@Override
public void setRawDataReceiver(RawDataChannel messageHandler) {
RawDataChannel decodingChannel = raw -> {
System.out.println("Length: " + raw.getSize())
messageHandler.receiveData(raw);
};
origin.setRawDataReceiver(decodingChannel);
}
@Override
public void start() throws IOException {
origin.start();
}
@Override
public void stop() { origin.stop();
}
@Override
public void destroy() { origin.destroy();
}
@Override
public InetSocketAddress getAddress() {
return origin.getAddress();
}
}
Тем не менее, трудно связать эти длины и ответы.
Я использую следующий класс для анализа RawData:
import org.eclipse.californium.core.coap.Message;
import org.eclipse.californium.core.network.serialization.DataParser;
import org.eclipse.californium.elements.RawData;
public class ParsedPacket {
private final RawData packet;
public ParsedPacket(RawData packet) {
this.packet = packet;
}
@Override
public String toString() {
Message msg = null;
DataParser parser = new DataParser(packet.getBytes());
if (parser.isEmpty()) {
msg = parser.parseEmptyMessage();
} else if (parser.isRequest()) {
msg = parser.parseRequest();
} else if (parser.isResponse()) {
msg = parser.parseResponse();
}
return (msg == null) ? "" : msg.toString();
}
}
При этом вы можете связать конкретный ответ и общую длину, используя, например, MID и токен.
Подводный камень в том, что для этого вам нужно использовать глобальное хранилище.
Я не рекомендую использовать его для производства. За исключением некоторых редких случаев, например, выведите некоторую информацию о пакете + длину. Который также может быть покрыт включением некоторого соответствующего уровня регистратора Калифорнии.
Так что это буквально плохая практика.
MessageTracer и сериализация сообщений
Вы можете реализовать интерфейс org.eclipse.californium.core.network.interceptors.MessageInterceptor, скажем, с классом MessageLengthTracer.
client.setEndpoint(...);
client.endpoint().setMessageTracer(new MessageLengthTracer());
Там вы можете сериализовать сообщения, используя org.eclipse.californium.core.network.serialization.DataSerializer с техникой, аналогичной предыдущему обходному пути, и получить их длины.
Однако это тоже обходной путь, и здесь есть две ловушки - возможная неточность длины и двойная сериализация.
PS Я буду рад, если кто-то скажет, что я неправ, и укажет мне чистый способ сделать это.