Сотрудничество между boost :: asio и стандартным интерфейсом сокета C - PullRequest
2 голосов
/ 15 июня 2011

В настоящее время я работаю над небольшим проектом: есть протокол для отправки некоторых строк через UDP, реализованный со стандартным интерфейсом C.

Хотя он работает довольно хорошо, я хотел бы переписать его еще с некоторымисложный C ++ (рассмотрим это упражнение).

В настоящее время это что-то вроде этого: Клиент хочет эту строку, поэтому он отправляет следующее struct:

struct request {
  uint8_t msg_type;// == 1
  uint64_t key; // generated randomly to identify each request
}

В новой реализации я хочуиспользуйте boost::asio, поэтому на сервере у меня есть следующий фрагмент кода:

boost::asio::io_service io_service;
boost::asio::ip::udp::endpoint client_endpoint;
boost::asio::ip::udp::socket socket(io_service,
        boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(),
        m_serverPort));
boost::asio::streambuf sb;
boost::asio::streambuf::mutable_buffers_type mutableBuf =
        sb.prepare(sizeof(request));
size_t received_bytes = socket.receive_from(mutableBuf, client_endpoint);
sb.commit(received_bytes);

request r;
std::istream is(&sb);
is >> msg_type;
is >> key;
key = __bswap64(key); // I'm using network byteorder for numbers sent with this protocol
                      // and there's no ntohll function on Snow Leopard (at least I can't
                      // find one)
sb.consume(received_bytes);

И вот моя проблема: значение «ключа», которое я пытаюсь получить таким образом, неверно - я имею в виду, что я получаю что-то, чтоЯ не отправлял.

Вот мои подозрения:

  1. __ bswap64 не конвертирует сеть в хост (little-endian) byteorder
  2. Я неправильно понял, как использовать boost:: asio :: streambuf с потоками
  3. Существует некоторая несовместимость между старым интерфейсом C и boost (но я так не думаю, потому что я обнаружил, что функции boost просто обертки для него)

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

struct __attribute__ ((packed)) CITE_MSG_T
{
        uint8_t msg_id;
        uint64_t key; // must be the same as in request
        uint16_t index; // part number
        uint16_t parts; // number of all parts
    CITE_PART_T text; // message being sent
};

//where CITE_PART_T is:
struct __attribute__ ((packed)) CITE_PART_T
{ 
        uint16_t data_length;
        char* data;
};

и следующий фрагмент кода: http://pastebin.com/eTzq6AWQ. К сожалению, есть еще одна ошибка, и я снова читаю то, что у меня естьне отправлено - replyMsg.parts и replyMsg.index всегда равны 0, хотя старая реализация говорит, что они, например, 3 и 10. Что не так в этот раз?Как вы можете видеть, я забочусь о заполнении и использую read вместо operator >>.Если вы удивляетесь, почему я читаю эту структуру поле за полем, вот ответ: сервер отправляет две разные структуры, обе начинаются с msg_id, одна в случае успеха и другая в случае сбоя.Прямо сейчас я просто не знаю, как это сделать иначе.

Ответы [ 2 ]

3 голосов
/ 15 июня 2011

Вы используете форматированный ввод, как если бы отправляемые данные были текстовыми - вам нужен un форматированный ввод. Прочитайте о функции-члене std::istream::read, так как это то, что вы должны использовать, а не operator>>.

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

0 голосов
/ 15 июня 2011

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

struct request {
    uint8_t msg_type;
    char __pad__[3]; // or 7 on 64-bit machine.
    uint64_t key;
};

Это можно исправить, скажем, в GCC, с атрибутами (см.Руководство GCC ):

struct __attribute__ ((__packed__)) request { ...

И да, я упустил тот факт, что вы пытаетесь читать текст вместо двоичного файла.Исправьте это сначала, укусите выравниванием / заполнением позже:)

...