Страницы

Поиск по вопросам

вторник, 17 марта 2020 г.

Замена данных в TCP пакете

#java #замена #tcp


В общем, есть два устройства.
Одно отсылает пакеты, а другое, соответственно, их принимает, изменяет и дальше отправляет
в сеть. 

И тут еще суть в том, что нужно оставить заголовки пакета, окончание, а содержимое
заменить на другое. 

То есть что получается: мне нужно поднять сервер, получить пакет, убрать из него
содержимое и вставить своё. Отправить пакет дальше. Даже схемка есть: 

Вот - N - это количество "D".



Не понимаю, с чего начинать, т.к. с этим сталкиваюсь в первый раз. И хотелось бы
понять, что нарисовано на картинке.
    


Ответы

Ответ 1



Тут вроде ничего сложного. На картинке показана структура 2-х пакетов: Сообщение, которое к вам приходит. Сообщение, которое вы должны отослать. По каждому сообщению подробно расписана структура следования байтов (Б1, Б2 и т.д.), также показано, какую часть и куда нужно переносить. Тело исходного сообщения состоит из массива данных структуры "D", каждый элемент по 6 байт. Но я сейчас какие-то прописные истины перечислил)), которые вы и сами, наверное, поняли) Но вот что мне не понятно по этому рисунку: Во-первых, "Измерительное сообщение 98 байт максимум" - следовательно, пакет нефиксированной длины, а как мы узнаем об окончании пакета? + не хватает 10 байт в описании, максимум 98, а на картинке расписано только 88 байт. Может, еще есть какая-нибудь информация? Во-вторых, тело исходного сообщения на картинке 84 байта, а уместить его нужно в 103 байта, с ним производятся какие-то манипуляции? Или нужно добивать нулями до определенной длинны? =============================================== Все еще остаются вопросы) вот смотрите примерный алгоритм На вашем сервере(на рис - прибор 2), считываем поток байт, для начала берем первый байт и сверяем заголовок, судя по рисунку заголовок всегда 23 если да то продолжаем читать, если нет то нужно больше информации о других пакетах и дальнейших действиях Теперь когда мы поняли что за пакет, нам нужно узнать остальные данные, для этого нужно понять длинну пакета, и тут опять непонятно как ее вычислить она всегда фиксирована и равна = 113 байт ( тогда вам нужно считать еще 110 байт + crc(2 байта) ), или "N" - это количество D, как говорил @avp, тогда вам нужно считать еще один байт, будем считать что это count, тогда формула будет такая count * 6 + crc( 2 байта ) Когда вы получили тело сообщения, нужно сверить crc ( последние 2 байта), но тут не написано для какой части сообщения его сверять? Если crc совпал то теперь можно формировать новый пакет, но как его формировать тоже не совсем понятно

Ответ 2



Короче, вот что я сумел настрогать: Вот прибор 1: import java.io.*; import java.net.*; import java.util.*; import java.nio.ByteBuffer; import java.math.BigInteger; class TCPClient { public static void main(String argv[]) throws Exception { Random rand = new Random(); int[] keys = {20, 1480, 70, 1520, 1470, 60, 0, -16, -15, -14}; float[] values = {0.000f, 0.000f, 0.000f, 0.000f, 0.006f, 0.000f, 0f, 22.150f, 744.301f, 41.136f}; byte[] bots = new byte[88]; byte[] one_byte = new byte[4]; //one_byte = intToByteArray(023, 1); bots[0] = intToByteArray(23, 1)[0]; bots[1] = intToByteArray(14, 1)[0]; for(int i=2, key_store = 0; i < 81; i++, key_store++) { one_byte = intToByteArray(keys[key_store], 2); // код ЗХВ bots[i++] = one_byte[0]; bots[i++] = one_byte[1]; one_byte = FloatToByteArray(values[key_store]); // отчет float bots[i++] = one_byte[0]; bots[i++] = one_byte[1]; bots[i++] = one_byte[2]; bots[i++] = one_byte[3]; } one_byte = intToByteArray(rand.nextInt(), 2); // код CRC 16 bots[86] = one_byte[0]; bots[87] = one_byte[1]; for(int i=0; i < 88; i++) { System.out.print(bots[i] + " "); } Socket socket = new Socket("localhost", 6789); DataOutputStream outToServer = new DataOutputStream(socket.getOutputStream()); BufferedReader inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream())); outToServer.write(bots); int bytesWritten = outToServer.size(); System.out.println("Total " + bytesWritten + " bytes are written to stream."); String modifiedSentence = inFromServer.readLine(); System.out.println("FROM SERVER: " + modifiedSentence); socket.close(); } public static byte[] FloatToByteArray(float value) { int bits = Float.floatToIntBits(value); byte[] bytes = new byte[4]; bytes[0] = (byte)(bits & 0xff); bytes[1] = (byte)((bits >> 8) & 0xff); bytes[2] = (byte)((bits >> 16) & 0xff); bytes[3] = (byte)((bits >> 24) & 0xff); return bytes; } public static byte[] intToByteArray(int value, int length) { if(length == 2) { byte[] data = new byte[2]; data[0] = (byte) (value & 0xFF); data[1] = (byte) ((value >> 8) & 0xFF); return data; } else { BigInteger bigInt = BigInteger.valueOf(value); return bigInt.toByteArray(); } } static int crc16(final byte[] buffer) { int crc = 0xFFFF; for (int j = 0; j < buffer.length ; j++) { crc = ((crc >>> 8) | (crc << 8) )& 0xffff; crc ^= (buffer[j] & 0xff);//byte to int, trunc sign crc ^= ((crc & 0xff) >> 4); crc ^= (crc << 12) & 0xffff; crc ^= ((crc & 0xFF) << 5) & 0xffff; } crc &= 0xffff; return crc; } } Как я думаю, как оно работает: первые 2 байта - кодирую int в byte и записываю. Дальше идут структуры "D", содержащие по 6 байт, где первые 2 байта ключ, а остальные 4 - значение. Ну и в конце код CRC. Но что получается, на устройстве 2 я принимаю запрос так: Socket connectionSocket = welcomeSocket.accept(); BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream())); DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream()); while ((i = inFromClient.read()) != -1) { } и получаю int значение, когда должно приходить byte, отправлял же в byte. Что делать? Вообще правильно?

Комментариев нет:

Отправить комментарий