Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform - [40]
Мы рассмотрим это на примере простейшей из них — MsgSend():
>#include
>int MsgSend(int coid, const void *smsg, int sbytes,
> void *rmsg, int rbytes);
Аргументами функции MsgSend() являются :
• идентификатор соединения с целевым сервером (coid);
• указатель на передаваемое сообщение (smsg);
• размер передаваемого сообщения (sbytes);
• указатель на буфер для ответного сообщения (rmsg);
• размер ответного сообщения (rbytes);
Что может быть проще!
Передадим сообщение процессу с идентификатором 77 по каналу 1:
>#include
>char *smsg = "Это буфер вывода";
>char rmsg[200];
>int coid;
>// Установить соединение
>coid = ConnectAttach(0, 77, 1, 0, 0);
>if (coid == -1) {
> fprintf(stderr, "Ошибка ConnectAttach к 0/77/1!\n");
> perror(NULL);
> exit(EXIT_FAILURE);
>}
>// Послать сообщение
>if (MsgSend(
> coid, smsg, strlen(smsg) + 1, rmsg, sizeof(rmsg)) == -1) {
> fprintf (stderr, "Ошибка MsgSend\n");
> perror(NULL);
> exit (EXIT_FAILURE);
>}
>if (strlen(rmsg) > 0) {
> printf("Процесс с ID 77 возвратил \"%s\"\n", rmsg);
>}
Предположим, что процесс с идентификатором 77 был действительно активным сервером, ожидающим сообщение именно такого формата по каналу с идентификатором 1. После приема сообщения сервер обрабатывает его и в некоторый момент времени выдает ответ с результатами обработки. В этот момент функция MsgSend() должна возвратить ноль (0), указывая этим, что все прошло успешно. Если бы сервер послал нам в ответ какие-то данные, мы смогли бы вывести их на экран с помощью последней строки в программе (с тем предположением, что обратно мы получаем корректную ASCIIZ-строку).
Сервер
Теперь, когда мы рассмотрели клиента, перейдем к серверу. Клиент использовал функцию ConnectAttach() для создания соединения с сервером, а затем использовал функцию MsgSend() для передачи сообщений.
Под этим подразумевается, что сервер должен создать канал — то, к чему присоединялся клиент, когда вызывал функцию ConnectAttach(). Обычно сервер, однажды создав канал, приберегает его «впрок».
Канал создается с помощью функции ChannelCreate() и уничтожается с помощью функции ChannelDestroy():
>#include
>int ChannelCreate(unsigned flags);
>int ChannelDestroy(int chid);
Мы еще вернемся к обсуждению аргумента flags (в разделе «Флаги каналов», см. ниже), а покамест будем использовать для него значение 0 (ноль). Таким образом, для создания канала сервер должен сделать так:
>int chid;
>chid = ChannelCreate(0);
Теперь у нас есть канал. В этом пункте клиенты могут подсоединиться (с помощью функции ConnectAttach()) к этому каналу и начать передачу сообщений:
Связь между каналом сервера и клиентским соединением.
В терминах обмена сообщениями, сервер отрабатывает схему обмена в два этапа — этап «приема» (receive) и этап «ответа» (reply).
Взаимосвязь функций клиента и сервера при обмене сообщениями.
Обсудим сначала два простейших варианта соответствующих функций, MsgReceive() и MsgReply(), а далее посмотрим, какие есть варианты.
>#include
>int MsgReceive(int chid, void *rmsg, int rbytes,
> struct _msg_info *info);
>int MsgReply(int rcvid, int status, const void *msg,
> int nbytes);
Посмотрим, как соотносятся параметры:
Поток данных при обмене сообщениями.
Как видно из рисунка, имеются четыре элемента, которые мы должны обсудить:
1. Клиент вызывает функцию MsgSend() и указывает ей на буфер передачи (указателем smsg и длиной sbytes). Данные передаются в буфер функции MsgReceive() на стороне сервера, по адресу rmsg и длиной rbytes. Клиент блокируется.
2. Функция MsgReceive() сервера разблокируется и возвращает идентификатор отправителя rcvid, который будет впоследствии использован для ответа. Теперь сервер может использовать полученные от клиента данные.
3. Сервер завершил обработку сообщения и теперь использует идентификатор отправителя rcvid, полученный от функции MsgReceive(), передавая его функции MsgReply(). Заметьте, что местоположение данных для передачи функции MsgReply() задается как указатель на буфер (smsg) определенного размера (sbytes). Ядро передает данные клиенту.
4. Наконец, ядро передает параметр sts, который используется функцией MsgSend() клиента как возвращаемое значение. После этого клиент разблокируется.
Вы, возможно, заметили, что для каждой буферной передачи указываются два размера (в случае запроса от клиента клиента это sbytes на стороне клиента и rbytes на стороне сервера; в случае ответа сервера это sbytes на стороне сервера и rbytes на стороне клиента). Это сделано для того, чтобы разработчики каждого компонента смогли определить размеры своих буферов — из соображений дополнительной безопасности.
В нашем примере размер буфера функции MsgSend() совпадал с длиной строки сообщения. Давайте теперь рассмотрим, что происходит в сервере и как размер используется там.
Вот общая структура сервера:
>#include
>...
>void server(void) {
> int rcvid; // Указывает, кому надо отвечать
> int chid; // Идентификатор канала
> char message[512]; // Достаточно велик
> // Создать канал
> chid = ChannelCreate(0);
> // Выполняться вечно — для сервера это обычное дело
Одно из немногих изданий на русском языке, которое посвящено старейшей глобальной компьютерной сети "Fidonet". Сатирический справочник о жизни и смерти самого древнего сетевого сообщества, которое до сих пор существует среди нас.
В пособии излагаются основные тенденции развития организационного обеспечения безопасности информационных систем, а также подходы к анализу информационной инфраструктуры организационных систем и решению задач обеспечения безопасности компьютерных систем.Для студентов по направлению подготовки 230400 – Информационные системы и технологии (квалификация «бакалавр»).
В книге американских авторов — разработчиков операционной системы UNIX — блестяще решена проблема автоматизации деятельности программиста, системной поддержки его творчества, выходящей за рамки языков программирования. Профессионалам открыт богатый "встроенный" арсенал системы UNIX. Многочисленными примерами иллюстрировано использование языка управления заданиями shell.Для программистов-пользователей операционной системы UNIX.
Книга адресована программистам, работающим в самых разнообразных ОС UNIX. Авторы предлагают шире взглянуть на возможности параллельной организации вычислительного процесса в традиционном программировании. Особый акцент делается на потоках (threads), а именно на тех возможностях и сложностях, которые были привнесены в технику параллельных вычислений этой относительно новой парадигмой программирования. На примерах реальных кодов показываются приемы и преимущества параллельной организации вычислительного процесса.
Применение виртуальных машин дает различным категориям пользователей — от начинающих до IT-специалистов — множество преимуществ. Это и повышенная безопасность работы, и простота развертывания новых платформ, и снижение стоимости владения. И потому не случайно сегодня виртуальные машины переживают второе рождение.В книге рассмотрены три наиболее популярных на сегодняшний день инструмента, предназначенных для создания виртуальных машин и управления ими: Virtual PC 2004 компании Microsoft, VMware Workstation от компании VMware и относительно «свежий» продукт — Parallels Workstation, созданный в компании Parallels.
Книга содержит подробные сведения о таких недокументированных или малоизвестных возможностях Windows XP, как принципы работы с программами rundll32.exe и regsvr32.exe, написание скриптов сервера сценариев Windows и создание INF-файлов. В ней приведено описание оснасток, изложены принципы работы с консолью управления mmc.exe и параметрами реестра, которые изменяются с ее помощью. Кроме того, рассмотрено большое количество средств, позволяющих выполнить тонкую настройку Windows XP.Эта книга предназначена для опытных пользователей и администраторов, которым интересно узнать о нестандартных возможностях Windows.