Моделирование RPC и UniData с использованием Java
Я пытаюсь написать симулятор для RPC-сервера, чтобы я мог использовать библиотеку Java UniData. Если я декомпилирую их API, я вижу этот фрагмент кода.
private byte[] headerBuffer;
private int readHeaderLength() {
return ((this.headerBuffer[4] & 0xFF) << 24) +
((this.headerBuffer[5] & 0xFF) << 16) +
((this.headerBuffer[6] & 0xFF) << 8) +
((this.headerBuffer[7] & 0xFF) << 0);
}
Атрибут headBuffer заполняется чем-то следующим:
final Socket socket = new Socket("127.0.0.1", 31438);
final DataInputStream dataIn = new DataInputStream(socket.getInputStream());
dataIn.readFully(this.headerBuffer);
Судя по всему, кажется, что эта часть кода отвечает за инициализацию RPC-соединения с каким-либо сервером.
Чтобы смоделировать это, я создал сервер, который прослушивает этот порт и открывает поток вывода следующим образом:
@Override
public void run() {
try {
final DataInputStream dataIn = new DataInputStream(socket.getInputStream());
final DataOutputStream dataOut = new DataOutputStream(socket.getOutputStream());
final String connectionResponse = "SIMULATED_CONNECTION";
dataOut.write(connectionResponse.getBytes());
System.out.println("#### message sent");
while (true) {
final byte[] data = new byte[1024];
dataIn.readFully(data);
final String input = new String(data);
if (input == null || input.equals(".")) {
System.out.println("### the input line is " + input);
break;
}
System.out.println("## received message " + input);
}
} catch (final IOException e) {
System.out.println("Error handling request : " + e.getMessage());
} finally {
try {
socket.close();
} catch (final IOException e) {
System.out.println("## cant close socket " + e.getMessage());
}
}
}
Тем не менее, я не могу на всю жизнь понять, что readHeaderLength() действительно пытается извлечь из соединения. Хотя я вижу декомпилированный код, я лучше понимаю, что он пытается проанализировать. Я смотрю на этот сайт и этот ответ:
- 0xFF = 00000000 00000000 00000000 11111111 (означает 32-битное значение типа int)
значение & 0xFF = заменить все 0, которые перекрываются с 1 с нулями, кроме первых 8 бит
если this.headerBuffer[5] оценивает какое-либо значение, это может привести к... 01100100 00000101 & ...00000000 11111111 = 00000000 00000101
когда (this.headerBuffer[5] & 0xFF) оценивает, << 16 добавит еще 16 нулей справа.
Так что же на самом деле может содержать this.headerBuffer[] ?
Если я напишу что-то простое, как:
final String data = "sample";
final byte[] bytes = data.getBytes();
for (final byte bit : bytes) {
System.out.println(bit);
}
Я получаю вывод: 115 97 109 112 108 101
Следовательно, рассматриваемый метод, скорее всего, ищет какой-то хорошо отформатированный заголовок для синхронизации при установлении соединения RPC. Я попытался заглянуть на этот веб-сайт, чтобы понять, какой тип заголовка я должен передавать как часть ответа моего сервера, чтобы метод readHeaderLength() был в пользу связи, но пока не нашел четкого ответа.
- Мое понимание того, как метод readHeaderLength() работает правильно?
- Правильно ли я сделал вывод, что он, скорее всего, ищет заголовок RPC?
1 ответ
Байтовый массив headerBuffer содержит 4-байтовое значение int в позициях индекса массива 4, 5, 6, 7. Метод readHeaderLength просто превращает эти 4-байтовые значения байтового массива в фактическое значение типа int с помощью операций сдвига битов.
Редактировать: Скорее всего, это длина заголовка входного потока из сокета, после того как заголовок начинает тело потока. Я предлагаю исследовать больше, как этот код знает, что значение "длины заголовка" хранится в позициях индекса 4, 5, 6, 7. Это определено в заголовке RPC?