Перенос приложения с архитектуры с прямым порядком байтов на архитектуру с прямым порядком байтов

У меня есть TCP-сервер, разработанный на архитектуре x86 с использованием C под Linux с использованием berkley socker API. Сервер работает нормально, без проблем. Но теперь по некоторым причинам мне приходится запускать сервер на архитектуре MIPS, которая имеет архитектуру big-endian.

Сервер и клиенты взаимодействуют через набор предопределенных протоколов. Приведу пример того, как сервер отправляет клиентам простое сообщение:

struct echo_req req;

  req.header.version = OFP_VERSION;
  req.header.type = OFPT_ECHO_REQUEST;
  req.header.length = htons (sizeof req);
  req.header.xid = htonl(y);
  req.data = htonl (456);

char data[sizeof (req)];
data[0] = req.header.version;
data[1] = req.header.type;
memcpy (data + 2, &req.header.length, 2);
memcpy (data + 4, &req.header.xid, 4);
memcpy (data + 8, &req.data, 4);

  if ((send (sock_fd, &data, sizeof (data), 0) == -1))
    {
      printf ("Error in sending echo request message\n");
      exit (-1);
    }
printf("Echo Request sent!\n");

Как видите, я использую htonl и htons для любого типа длиннее байта, чтобы преобразовать его в сетевой порядок байтов. После составления пакета я сериализую и упаковываю данные в массив char и, наконец, отправляю их в сеть.

Теперь, прежде чем я запущу свой сервер на архитектуре с обратным порядком байтов, я хотел прояснить несколько вещей. По моему мнению, когда я memcpy собираю данные и упаковываю их, если я отправляю их по сети, это не должно вызывать проблем с архитектурой с прямым порядком байтов, поскольку memcpy будет выполнять побайтовое копирование данных в массив и, следовательно, там не должно быть проблем с порядком байтов при работе с обратным порядком байтов. Тем не менее, я хотел узнать мнение о вас, люди, которые, как я полагаю, знают намного больше, чем я, поскольку я все еще новичок в сетевом программировании :). Пожалуйста, помогите мне в этом, на правильном ли я пути или нет. Вся помощь очень ценится.

Спасибо


person Abdullah    schedule 27.04.2012    source источник
comment
То, что вы делаете, прекрасно. Преобразуйте в сетевой порядок байтов, прежде чем передавать его по сети. Обратный процесс, когда вы снимаете его. Больше нечего сказать.   -  person David Heffernan    schedule 28.04.2012
comment
Я хотел подтвердить часть memcpy. Тоже нормально?   -  person Abdullah    schedule 28.04.2012
comment
Я хотел узнать мнение о вас, люди там. Разве не для этого предназначен codereview.stackexchange.com?   -  person Robᵩ    schedule 30.04.2012
comment
Кроме того: порядок следования байтов — не единственная проблема. Вы должны убедиться, что sizeof (echo_req) одинакова на обеих платформах.   -  person Robᵩ    schedule 30.04.2012
comment
Привет, Роб. Как я уже упоминал, сервер и клиенты взаимодействуют через набор предопределенных протоколов, а echo_request является одной из многих структур, определенных в протоколе, поэтому размер всегда будет одинаковым на обоих концах. Что касается обзора кода, то это было бы слишком много, чтобы просить, поскольку общий LOC сервера составляет более 10 000 строк :/ Я буду очень рад, если кто-то сможет просмотреть все это :)   -  person Abdullah    schedule 01.05.2012


Ответы (2)


Да, memcpy просто копирует байты по порядку из источника в пункт назначения.

Не видя остальной части вашего кода, невозможно сказать, что вы использовали hton(l|s) везде, где нужно. Также возможно, что вы сделали что-то вроде копирования числа с плавающей запятой байт за байтом, что не обязательно работает, независимо от проблем с порядком байтов.

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

person Jerry Coffin    schedule 27.04.2012
comment
Да, я пытался убедиться, что использую htonl/htons везде, где это необходимо. Просто были некоторые оговорки относительно memcpy, поэтому лучше подтвердить это :). Большое спасибо. - person Abdullah; 28.04.2012

Убедились ли вы, что используете ntoh/ntos и при получении данных?

Кстати, вы должны просто использовать структуру для отправки данных; повторная сборка его в массив символов ничего не делает, кроме как требует процессорного времени и, возможно, приводит к ошибкам.

person mic_e    schedule 27.04.2012
comment
Если структура не упакована, вы не можете просто отправить ее как есть. Копирование — это попытка убедиться, что оно правильно упаковано. Тем не менее, у большинства компиляторов есть способ объявить структуру упакованной, и использование упакованной структуры приведет к более простому коду. - person tomlogic; 28.04.2012
comment
да, я убедился, что использую ntoh/ntos. Я упаковываю структуру, потому что, как упомянул tomlogic, отправка структур в том виде, в каком они есть, может вызвать проблемы из-за разного объявления структур разными компиляторами, особенно с такими архитектурами, как MIPS и ARM, которые не допускают невыровненный доступ к памяти, проблема даже усугубляется. Так что лучше упакуйте, на мой взгляд :) - person Abdullah; 28.04.2012
comment
@Abdullah - но тогда вы отправляете упаковку вместе с данными! В коде, который вы нам показываете, вы отправляете sizeof(echo_req) байт, который может варьироваться в зависимости от платформы. - person Robᵩ; 30.04.2012