Реализация коммуникационных протоколов в C/С++

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

Я буду использовать c/С++, и я свободен использовать библиотеки использования (BSD/BOOST/Apache), но не GPL. Я использовал С++ экстенсивно, поэтому использование возможностей С++ не является проблемой.

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

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

Обновление: Пример протокола, который я хочу реализовать, это что-то вроде SNEP.

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

Ответ 1

Начните с интерфейсов и сообщений.

Объявить интерфейсы сеанса, которые позволяют одноранговым узлам обмениваться сообщениями. Объявляйте сообщения как структуры С++ с простыми типами, например, ints, double, std::string и std::vectors. Например:

// these are your protocol messages
struct HelloRequest {
    uint32_t seq_no;
    // more stuff
};
struct HelloResponse {
    uint32_t seq_no;
    // more stuff
};

// Session callback for received messages
struct SessionReceiver {
    virtual void connected(Session*) = 0;
    virtual void receive(Session* from, HelloRequest msg) = 0;
    virtual void receive(Session* from, HelloResponse msg) = 0;
    virtual void disconnected(Session*) = 0;
};

// Session interface to send messages
struct Session {
    virtual void send(HelloRequest msg) = 0;
    virtual void send(HelloResponse msg) = 0;
};

// this connects asynchronously and then calls SessionReceiver::connected() with a newly established session
struct SessionInitiator {
    virtual void connect(SessionReceiver* cb, std::string peer) = 0;
};

// this accepts connections asynchronously and then calls SessionReceiver::connected() with a newly accepted session
struct SessionAcceptor {
    virtual void listen(SessionReceiver* cb, std::string port) = 0;
};

Затем проверьте свои интерфейсы, закодировав бизнес-логику, использующую эти интерфейсы. После того, как вы уверены, что интерфейсы позволяют реализовать требуемую логику, реализуйте интерфейсы и сериализуйте свои сообщения, используя предпочтительную фреймворк, управляемый событиями, например libevent или Boost.Asio.

Edit: Обратите внимание, что интерфейсы позволяют выполнять ложные или тестовые реализации. Также тот факт, что сериализация происходит за интерфейсом, означает, что для сверстников в процессе вам не нужно сериализовать и десериализовать сообщения, вы можете передать их как есть.

Ответ 2

Boost.ASIO довольно режет, когда речь заходит о асинхронной (или синхронной) сетевой коммуникации на С++

Ответ 3

Посмотрите Буферы протокола Google.

Из описания:

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

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

Это поможет вам с протоколами. При фактической передаче данных, ну, если вы сами не пишете ОС, должны быть некоторые примитивы, которые вы должны использовать. Трудно дать более точную помощь по реализации, если вы не предоставите более подробную информацию. Например, какой канал связи вы используете? Ethernet?

Но, как правило, вы должны сделать ISR как можно короче. В таких решениях, которые обычно означают копирование данных в кольцевой буфер. Таким образом, вам не нужно выделять память в ISR. ISR после копирования данных должен информировать верхние слои пакета. Если вы можете использовать DMA, используйте это. В этом случае может быть возможно отправить уведомление, прежде чем вы даже начнете передачу DMA.

Вы также можете проверить Драйверы устройств Linux, глава 10 в частности. Проверьте часть о нижнем и верхнем половинах.