Сообщение сокета C++ содержит дополнительный символ ASCII 0

Так что это действительно странная проблема. У меня есть приложение Java, которое действует как сервер, прослушивает и принимает входящие клиентские подключения, а затем считывает данные (XML) из сокета. Используя мой клиентский драйвер Java, все работает отлично. Я получаю сообщения, как и ожидалось. Однако, используя мой клиентский драйвер C++ только для первого сообщения, самый первый символ читается как ASCII 0 (отображается как маленькая коробка). Мы используем стандартный API сокетов в C++, отправляя char* (мы сделали char*, std::string и просто текст в кавычках).

Я использовал Wireshark, чтобы пронюхать пакет, и, конечно же, он там, вне сети. Правда, я не делал того же на клиентском компьютере. Мой аргумент заключается в том, что это действительно не должно иметь значения, но поправьте меня, если это предположение неверно.

Итак, мой вопрос: какого черта? Почему только первое сообщение содержит эти дополнительные предваряющие данные, а все остальные сообщения в порядке? Есть ли какой-нибудь маленький трюк, чтобы заставить вещи работать?


person Dave    schedule 09.12.2009    source источник
comment
Какая ОС клиентская машина?   -  person Jason Orendorff    schedule 10.12.2009
comment
Windows XP на обоих. На самом деле они находятся на одной машине, но та же проблема возникает в сети. Это по сети, которую я тестировал с помощью Wireshark.   -  person Dave    schedule 10.12.2009


Ответы (3)


Скорее всего проблема в кодировке. Если вы просто используете char * для своего клиента C++, вы предполагаете кодировку ASCII (в лучшем случае), в то время как Java использует Unicode (или UTF, я не помню, какой) внутри и испускает UTF-8 (IIRC) по умолчанию.

Либо ваш Java-сервер выдает 7-битный/символьный ASCII, либо ваш клиент C++ читает кодировку, которую выдает Java.

Ааа. Мне придется провести некоторое время, свернувшись калачиком с Google у камина, чтобы выяснить, как сопоставить кодировку, но это дает мне возможность двигаться дальше. Мне, вероятно, придется изменить свою кодировку Java, чтобы она соответствовала той, что использует С++, поскольку это соответствует сценарию клиента. Любой, у кого есть хорошая ссылка, дополнительная информация или фрагмент кода, пожалуйста, опубликуйте.

Если ваш XML упакован в виде строки, вы можете использовать getBytes() для кодирования:

byte [] asciiEncodedBytes = myString.getBytes("US-ASCII");

РЕДАКТИРОВАТЬ: Прошло некоторое время с тех пор, как я был на земле Java, но не похоже, что Java имеет какие-либо потоки кодирования ASCII в основной библиотеке. Я нашел этот класс, который, очевидно, будет обертывать Поток кодирования ASCII для вас. К счастью, он находится в проекте с открытым исходным кодом, поэтому вы можете извлечь из него уроки для своего сервер.

person Randolpho    schedule 09.12.2009
comment
UTF — это кодировка Unicode. Проклятое соглашение об именах .NET framework - person Vinko Vrsalovic; 10.12.2009
comment
Ааа. Мне придется провести некоторое время, свернувшись калачиком с Google у камина, чтобы выяснить, как сопоставить кодировку, но это дает мне возможность двигаться дальше. Мне, вероятно, придется изменить свою кодировку Java, чтобы она соответствовала той, что использует С++, поскольку это соответствует сценарию клиента. Любой, у кого есть хорошая ссылка, дополнительная информация или фрагмент кода, пожалуйста, опубликуйте. - person Dave; 10.12.2009
comment
Да, меня ужасно испортили. :) - person Randolpho; 10.12.2009
comment
Итак, видимо, сегодня вечером мы с Google поссоримся - сегодня вечером у меня не будет вечеринки у костра. совет getBytes — чистое золото. Если кодировка С++ - ascii (наверняка), то вы, вероятно, только что решили мою проблему. - person Dave; 10.12.2009
comment
Я не понимаю, как проблема может быть на стороне Java, если в Wireshark виден ошибочный нулевой байт. - person Jason Orendorff; 10.12.2009
comment
Поскольку данные представляют собой XML, было бы лучше использовать синтаксический анализатор XML, который должен определить кодировку для вас, чем пытаться самостоятельно выяснить проблемы с кодировкой. - person Jason Orendorff; 10.12.2009
comment
Я использую Castor для привязки данных. Проблема, кажется, оторваться от провода. - person Dave; 10.12.2009

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

Я бы запустил Wireshark на клиентском компьютере, чтобы убедиться, что проблема действительно возникает там. Теоретически это мог сделать какой-то плохо работающий маршрутизатор или что-то в этом роде (хотя очень трудно поверить).

Затем я проверял бы аргументы API-интерфейсов сокетов во время фактического выполнения программы с помощью отладчика.

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

person Jason Orendorff    schedule 09.12.2009
comment
Объяснение Рандольфо гораздо правдоподобнее. Проблем с совместимостью предостаточно. - person Vinko Vrsalovic; 10.12.2009
comment
Наиболее вероятное объяснение — ошибка в программе на C++. - person Jason Orendorff; 10.12.2009
comment
Да, но проверка проблем с маршрутизатором или драйвером перед проверкой проблем взаимодействия - не лучший способ решить проблему, IMO. - person Vinko Vrsalovic; 10.12.2009
comment
Хорошее эмпирическое правило при отладке сложной проблемы: если проверить работоспособность легко, сделайте это. Вот почему я предлагаю сначала запустить Wireshark. Это займет всего секунду. - person Jason Orendorff; 10.12.2009

Итак, кодировка не сработала. В конце концов, я просто сделал вызов substring(startIndex) для входящего сообщения, используя xmlMessage.indexOf("<") в качестве начального индекса. Это может быть не элегантно, но это сработает. И коробка, останется загадкой. Я ценю понимание, которое вы трое предоставили.

person Dave    schedule 10.12.2009