русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

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

Каналы

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

Именованные и анонимные каналы

Существуют две разновидности каналов Pipe – именованные (Named Pipes) и анонимные (Anonymous Pipes).
Именованным каналам при создании присваивается имя, которое доступно для других процессов. Зная имя какой-либо рабочей станции в сети, процесс может получить доступ к каналу, созданному на этой рабочей станции.
Анонимные каналы обычно используются для организации передачи данных между родительскими и дочерними процессами, запущенными на одной рабочей станции или на “отдельно стоящем” компьютере.

Именна каналов


Имена каналов в общем случае имеют следующий вид:
\\ИмяСервера\pipe\ИмяКанала
Если процесс открывает канал, созданный на другой рабочей станции, он должен указать имя сервера. Если же процесс создает канал или открывает канал на своей рабочей станции, вместо имени указывается символ точки:
\\.\pipe\ИмяКанала
В любом случае процесс может создать канал только на той рабочей станции, где он запущен, поэтому при создании канала имя сервера никогда не указывается.

Создание канала

Для создания именованных и анонимных каналов Pipes используются функции CreatePipe и CreateNamedPipe.
Установка соединения с каналом со стороны сервера.

После того как серверный процесс создал канал, он может перейти в режим соединения с клиентским процессом. Соединение со стороны сервера выполняется с помощью функции ConnectNamedPipe.

Установка соединения с каналом со стороны клиента.

Для создания канала клиентский процесс может воспользоваться функцией CreateFile.

Отключение серверного процесса от клиентского процесса.

Установив канал с клиентским процессом при помощи функции ConnectNamedPipe, серверный процесс может затем разорвать канал, вызвав для этого функцию DisconnectNamedPipe.

Закрытие идентификатора канала.

Если канал больше не нужен, после отключения от клиентского процесса серверный и клиентский процессы должны закрыть его идентификатор функцией CloseHandle.

Запись и чтение данных в канале.

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

Пример. Передача данных (синхронная) от программы-клиента программе-серверу с помощью именованного канала на одной рабочей станции.

Программа-сервер

#include <windows.h>
#include <stdio.h>
#include <conio.h>
BOOL   fConnected; // Флаг успешного создания канала
HANDLE hNamedPipe; // Идентификатор канала Pipe
LPSTR  lpszPipeName = "\\\\.\\pipe\\$MyFirstPipe"; // Имя создаваемого канала
char   szBuf[512]; // Буфер для приема данных из канала
DWORD  cbRead; // Количество байт данных, принятых через канал

int main()
{
// Создаем канал Pipe с именем lpszPipeName
hNamedPipe = CreateNamedPipe(
lpszPipeName, PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 512, 512, 5000, NULL);
// Если возникла ошибка, завершаем работу приложения
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
printf("Error Pipe Creating!!!\n");
getch();
return 0;
}
// Ожидаем соединения со стороны клиента
fConnected = ConnectNamedPipe(hNamedPipe, NULL);
// Если возникла ошибка, завершаем работу приложения
if(!fConnected)
{
printf("Error Pipe Connecting!!!\n");
CloseHandle(hNamedPipe);
getch();
return 0;
}
// Получение данных из канала
if(ReadFile(hNamedPipe, szBuf, 512, &cbRead, NULL))
printf("Received %d bytes: <%s>\n", cbRead, szBuf);
else printf("Error Data Transfer!!!\n");
CloseHandle(hNamedPipe);
getch();
return 0;
}

Программа-клиент

#include <windows.h>
#include <stdio.h>
#include <conio.h>
HANDLE hNamedPipe; // Идентификатор канала Pipe
DWORD  cbWritten; // Количество байт, переданных через канал
char   szBuf[256]; // Буфер для передачи данных
LPSTR  lpszPipeName = "\\\\.\\pipe\\$MyFirstPipe"; // Имя создаваемого канала

int main()
{
// Установка соединения с процессом PIPES
hNamedPipe = CreateFile(lpszPipeName, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
// Если возникла ошибка, завершаем работу приложения
if(hNamedPipe == INVALID_HANDLE_VALUE)
{
printf("Error Pipe Creating!!!\n");
getch();
return 0;
}
// Передача данных серверному процессу
strcpy(szBuf,"Test Pipe Connection");
if(!WriteFile(hNamedPipe, szBuf, strlen(szBuf) + 1, &cbWritten, NULL))
// Если произошла ошибка, выдаем сообщение
printf("Error Data Transfer!!!\n");
else printf("Transferred %d bytes: <%s>\n", cbWritten, szBuf);
// Закрываем идентификатор канала
CloseHandle(hNamedPipe);
getch();
return 0;
}

Почтовые ящики

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

 

Создание почтового ящика

Mailslot создается серверным процессом с помощью специально предназначенной для этого функции CreateMailslot. После создания серверный процесс получает идентификатор Mailslot. Пользуясь этим идентификатором, сервер может читать сообщения, посылаемые в почтовый ящик клиентскими процессами. Однако сервер не может выполнять над Mailslot операцию записи, так как этот почтовый ящик предназначен только для односторонней передачи данных – от клиента к серверу.

Имя Mailslot задается аналогично имени канала Pipe (приведен синтаксис для создания почтового ящика на своей рабочей станции):
\\.\mailslot\[Путь]ИмяПочтовогоЯщика
Чтобы открыть Mailslot, созданный на другой рабочей станции в сети, строка имени канала должна иметь следующий вид:
\\ИмяРабочейСтанции\mailslot\[Путь]ИмяПочтовогоЯщика
Можно открыть канал для передачи сообщений всем рабочим станциям заданного домена. Для этого необходимо задать имя по следующему образцу:
\\ИмяДомена\mailslot\[Путь]ИмяПочтовогоЯщика
Для передачи сообщений одновременно всем рабочим станциям сети первичного домена имя задается следующим образом:
\\*\mailslot\[Путь]ИмяПочтовогоЯщика
В последних двух случаях размер сообщений ограничивается 400 байтами.
Запись и чтение данных в почтовых ящиках осуществляется аналогично записи и чтению в каналах.

Определение состояния Mailslot


Серверный процесс может определить текущее состояние Mailslot по его идентификатору с помощью функции GetMailslotInfo.

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

Программа-сервер

#include <windows.h>
#include <stdio.h>
#include <conio.h>
BOOL   fReturnCode; // Код возврата из функций
DWORD  cbMessages; // Размер сообщения в байтах
DWORD  cbMsgNumber; // Количество сообщений в Mailslot
HANDLE hMailslot; // Идентификатор Mailslot
LPSTR  lpszMailslotName = "\\\\.\\mailslot\\$MyFirstMailslot"; // Имя Mailslot
char   szBuf[512]; // Буфер для передачи данных через Mailslot
DWORD  cbRead; // Количество байт данных, принятых через Mailslot

int main()
{
// Создаем Mailslot, с именем lpszMailslotName
hMailslot = CreateMailslot(lpszMailslotName, 0,
MAILSLOT_WAIT_FOREVER, NULL);
// Если возникла ошибка, завершаем работу приложения
if(hMailslot == INVALID_HANDLE_VALUE)
{
printf("Error MailSlot Creating!!!\n");
getch();
return 0;
}
while (1)
{
// Определяем состояние канала Mailslot
fReturnCode = GetMailslotInfo(hMailslot, NULL,
&cbMessages, &cbMsgNumber, NULL);
if(!fReturnCode)
{
printf("Get MailSlotInfo Error!!!\n");
getch();
return 0;
}
// Если в Mailslot есть сообщения, читаем первое и выводим на экран
if(cbMsgNumber != 0)
{
if(ReadFile(hMailslot, szBuf, 512, &cbRead, NULL))
printf("Received %d bytes: <%s>\n", cbRead, szBuf);
else printf("Error Data Transfer!!!\n");
break;
}
}
getch();
CloseHandle(hMailslot);
return 0;
}

Программа-клиент

#include <windows.h>
#include <stdio.h>
#include <conio.h>
HANDLE hMailslot; // Идентификатор Mailslot
char   szMailslotName[256]; // Буфер для имени Mailslot
char   szBuf[512]; // Буфер для передачи данных через Mailslot
DWORD  cbWritten; // Количество байт, переданных через Mailslot
LPSTR  lpszMailslotName = "\\\\.\\mailslot\\$MyFirstMailslot"; // Имя Mailslot

int main()
{
// Создаем Mailslot
hMailslot = CreateFile(
lpszMailslotName, GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
// Если возникла ошибка, завершаем работу приложения
if(hMailslot == INVALID_HANDLE_VALUE)
{
printf("CreateFile Error!!!\n");
getch();
return 0;
}
// Посылка данных через Mailslot
strcpy(szBuf,"Test MailSlot Connection");
if(!WriteFile(hMailslot, szBuf, strlen(szBuf) + 1, &cbWritten, NULL))
// Если произошла ошибка, выдаем сообщение
printf("Error Data Transfer!!!\n");
else printf("Transferred %d bytes: <%s>\n", cbWritten, szBuf);
CloseHandle(hMailslot);
getch();
return 0;
}

 

Просмотров: 18064

Вернуться воглавление




Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Полезен материал? Поделись:

Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.