Лабораторная работа: Передача данных с использованием почтовых ящиков и ждущих таймеров

Цель работы

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

Список используемых системных вызовов

CreateMailslot, CreateFile, GetMailslotInfo, SetMailslotInfo, ReadFile, ReadFileEx, WriteFile, WriteFileEx, CreateWaitableTimer, OpenWaitableTimer, SetWaitableTimer, TimerAPCProc, CancelWaitableTimer, SleepEx, WaitForSingleObjectEx,
WaitForMultipleObjectsEx.

Методические указания

Почтовые ящики позволяют процессам обмениваться данными в пределах локальной сети Microsoft. Для создания почтового ящика на стороне сервера используется функция CreateMailslot. На стороне клиента используется функция работы с файлами CreateFile. Для записи и чтения из почтового ящика используются функции ReadFile и WriteFile соответственно. (Для работы почтового ящика совместно с ждущим таймером следует использовать функции ReadFileEx и WriteFileEx). Для получения информации о наличии данных в почтовом ящике на стороне сервера используется функция GetMailslotInfo. Следует обратить внимание, что в ОС Windows9X эта функция работает некорректно и значение параметра lpNextSize необходимо проверять на наличие сообщения следующим способом:
if ((dwNextSize | 0xffff0000) != MAILSLOT_NO_MESSAGE)
{
     // Данные есть
}
Ждущие таймеры используются для выполнения определенных действий в заданное время или через заданный интервал времени. Ждущий таймер создается с помощью функции CreateWaitableTimer. Ожидание срабатывания таймера можно производить с помощью WaitFor-функций. Другой способ – задать специальную callback-функцию, которая выполнится сразу после перехода таймера в сигнальный режим. При этом нить должна находится в особом состоянии, называемом «тревожным» (alertable). Нить находится в этом состоянии при выполнении функций ожидания с суффиксом Ex: ReadFileEx, WriteFileEx, SleepEx, WaitForSingleObjectEx, WaitForMultipleObjectsEx, и других.
Ждущие таймеры, как и мьютексы, бывают с ручным сбросом и синхронизирующие. Синхронизирующие таймеры используются для временной синхронизации процессов и нитей или для однократного вызова callback-функции. Ждущие таймеры используются для периодического вызова callback-функции.
С помощью ждущих таймеров можно легко программировать максимальное время ожидания поступления данных в почтовый ящик.

Задания

         11. Разработать программу, передающую на сервер данные о версии операционной системы (функция GetVersionEx).

                                                          
Листинг программы.
Первая программа:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>

void main()
{
            HANDLE hMailSlot;
            char chBuffer[256],tmp[256];

            DWORD dwBytesRead;
            OSVERSIONINFO VerSys;  //в данной структуре хранится информация о версии системы
           
            //присоединяемся к почтовому ящику
            // для посылки сообщения серверу необходимо испоьзовать следующую строку
            // "\\\\Servers\\mailslot\\messngr"
            hMailSlot = CreateFile("\\\\.\\mailslot\\myslot",GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
            if (hMailSlot==INVALID_HANDLE_VALUE)
            {
                        printf("\n Error connect to mailslot!!!");
                        exit(0);
            }
           
            //пишем информацию в почтовый ящик
            ZeroMemory(&VerSys, sizeof(OSVERSIONINFO));                    //Функция ZeroMemory заполняет указанный фрагмент памяти нулями
            //Перед использованием этой функции надо указать размер структуры
            //в параметре dwOSVersionInfoSize используя sizeof(OSVERSIONINFO).
            VerSys.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
            if(GetVersionEx((OSVERSIONINFO*)&VerSys)==false)printf("\n :((");
           
            //компонуем строку о версии ОС
            if(VerSys.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
            {
                        if(VerSys.dwMinorVersion==0)
                                   strcpy(chBuffer,"Windows 95 Version[");
                        else if(VerSys.dwMinorVersion==10)
                                   strcpy(chBuffer,"Windows 98 Version[");
                        else if(VerSys.dwMinorVersion==90)
                                   strcpy(chBuffer,"Windows ME Version[");
            }
            else if (VerSys.dwPlatformId == VER_PLATFORM_WIN32_NT)
            {
                        if(VerSys.dwMajorVersion==3)
                                   strcpy(chBuffer,"Windows NT 3.51 Version[");
                        else if(VerSys.dwMajorVersion==4)
                                   strcpy(chBuffer,"Windows NT 4.0 Version[");
                        else if(VerSys.dwMajorVersion==5)
                        {
                                   if(VerSys.dwMinorVersion==0)
                                               strcpy(chBuffer,"Windows 2000 Version[");
                                   if(VerSys.dwMinorVersion==1)
                                               strcpy(chBuffer,"Windows XP Version[");
                                   if(VerSys.dwMinorVersion==2)
                                               strcpy(chBuffer,"Windows .NET Server Version[");
                        }
            }
           
            itoa(VerSys.dwMajorVersion,tmp,10);
            strcat(chBuffer,tmp);
            strcat(chBuffer,".");
            itoa(VerSys.dwMinorVersion,tmp,10);
            strcat(chBuffer,tmp);
            strcat(chBuffer,".");
            itoa(VerSys.dwBuildNumber,tmp,10);
            strcat(chBuffer,tmp);
            strcat(chBuffer,"]");
            strcat(chBuffer,"  ");
            strcat(chBuffer, VerSys.szCSDVersion);

            if (WriteFile(hMailSlot, &chBuffer, strlen(chBuffer), &dwBytesRead, NULL)!=0)
                        printf("\n Ok Write!!!");
            getch();          
       
}
Вторая программа:
#include <windows.h>
#include <stdio.h>
#include <conio.h>

void main()
{
            HANDLE hMailSlot;
            char chBuffer[256];
            DWORD dwBytesRead;
           
            //создадим сервер почтового слота
            hMailSlot = CreateMailslot("\\\\.\\mailslot\\myslot",0, MAILSLOT_WAIT_FOREVER,NULL);
            if (hMailSlot==INVALID_HANDLE_VALUE)
            {
                        printf("\n Error creating mailslot!!!");
                        exit(0);
            }
           
            //прочитаем информацию из почтового ящика
            if (ReadFile(hMailSlot, &chBuffer, 255, &dwBytesRead, NULL)!=0)
            {
                        chBuffer[dwBytesRead]=NULL;
                        printf("\n Ok read:  %s",chBuffer);
            }
            getch();                   

}

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

Комментариев нет:

Отправить комментарий