Перенос символов из java в c ++: проблема с порядком байтов - PullRequest
0 голосов
/ 27 декабря 2018

Я столкнулся с проблемой извращения после того, как вложил свои руки в старый унаследованный проект.Проект состоит из приложения Java и приложения c ++, которые взаимодействуют с сокетами.Оба приложения предназначены для работы в кроссплатформенных средах, поэтому я был бы рад сделать код как можно более универсальным.

В итоге я переписал части логики связи, поскольку в предыдущей реализации были некоторые проблемы синостранные персонажи.Теперь я столкнулся с проблемой с порядком байтов, которую, я надеюсь, кто-нибудь сможет мне объяснить.

Программное обеспечение Java записывает сообщения в сокет с помощью OutputStreamWriter, используя кодировку UTF-16LE, следующим образом.

OutputStream out = _socket.getOutputStream();
outputWriter = new OutputStreamWriter(new BufferedOutputStream(out), "UTF-16LE");

// ... create msg

outputWriter.write(msg, 0, msg.length());
outputWriter.flush();

Программа c ++ получает сообщение символ за символом следующим образом:

char buf[1];
std::queue<char> q;
std::u16string recUtf16Msg;

do {
    int iResult = recv(socket, buf, 1, 0);

    if (iResult <= 0)
        break; // Error or EOS

    for (int i = 0; i < iResult; i++) {
        q.push(buf[i]);
    }

    while (q.size() >= 2) {
        char firstByte = q.front();
        q.pop();
        char secondByte = q.front();
        q.pop();
        char16_t utf16char = (firstByte << (sizeof(char) * CHAR_BIT)) ^
                             (0x00ff & secondByte);

        // Change endianness, if necessary
        utf16char = ntohs(utf16char);

        recUtf16Msg.push_back(utf16char);
    }

    // ... end of message check removed for clarity
} while (true);

Теперь проблема, с которой я действительно сталкиваюсь, заключается в том, что приведенный выше код действительно работает, но я не совсем уверен, почему.Сторона c ++ написана для получения сообщений, которые используют сетевой порядок байтов (с прямым порядком байтов), но кажется, что java отправляет данные, используя кодировку с прямым порядком байтов.

На стороне c ++ мы даже используем функцию ntons для изменения порядка байтов натот, который требуется на хост-машине.В соответствии со спецификацией, я понимаю, что hton должен выполнять порядок байтов подстановки, если платформа хоста использует порядок байтов с прямым порядком байтов.Однако ntonhs на самом деле меняет порядковый номер получаемых символов с прямым порядком байтов, который заканчивается как большой порядок байтов и программное обеспечение работает безупречно.

Может быть, кто-то может указать, что именно происходит?Я случайно переключаю байты уже при создании utf16char?Почему htons заставляет все работать, а кажется, что он действует совершенно противоположно документации?Для компиляции я использую Clang с libc ++.

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

...