Системное программирование в среде Windows
Шрифт:
hSrvrThread[iTh] = (HANDLE)_beginthreadex (NULL, 0, Server, &ThArgs[iTh], 0, &ThreadId);
}
/* Дождаться завершения всех потоков и "убрать мусор". */
/* … */
return 0;
}
static DWORD WINAPI Server(LPTHREAD_ARG pThArg)
/* Функция потока сервера.
Имеется по одному потоку для каждого
потенциального клиента. */
{
HANDLE hCp, hTmpFile = INVALID_HANDLE_VALUE;
HANDLE hWrEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD nXfer, KeyIndex, ServerNumber;
/* … */
BOOL Success, Disconnect, Exit = FALSE;
LPOVERLAPPED pOv;
OVERLAPPED ovResp = {0, 0, 0, 0, hWrEvent}; /*Для ответных сообщений.*/
/* Чтобы избежать помещения перекрывающейся операции в очередь порта завершения, должен быть установлен младший бит события. Несмотря на всю странность этого способа, он документирован. */
ovResp.hEvent = (HANDLE)((DWORD)hWrEvent | 0x1);
GetStartupInfo(&StartInfoCh);
hCp = pThArg->hCompPort;
ServerNumber = pThArg->ThreadNo;
while(!ShutDown && !Exit) __try {
Success = FALSE; /* Устанавливается только в случае успешного завершения всех операций. */
Disconnect = FALSE;
GetQueuedCompletionStatus(hCp, &nXfer, &KeyIndex, &pOv, INFINITE);
if (Key [KeyIndex].Type == 0) { /* Соединение установлено. */
/* Открыть временный файл с результатами для этого соединения. */
hTmpFile = CreateFile(pThArg->TmpFileName, /* … */);
Key[KeyIndex].Type = 1;
Disconnect = !ReadFile(Key[KeyIndex].hNp, &Key[KeyIndex].Req, RQ_SIZE, &nXfer, &Key[KeyIndex].Ov) && GetLastError == ERROR_HANDLE_EOF; /* Первая операция чтения. */
if (Disconnect) continue;
Success = TRUE;
} else {
/* Чтение завершилось. Обработать запрос. */
ShutDown = ShutDown || (_tcscmp (Key[KeyIndex].Req.Record, ShutRqst) == 0);
if (ShutDown) continue;
/* Создать процесс для выполнения команды. */
/* … */
/* Отвечать по одной строке за один раз. На данном этапе удобно использовать функции библиотеки С для работы со строками. */
fp = _tfopen(pThArg->TmpFileName, _T("r"));
Response.Status = 0;
/* Поскольку младший бит события установлен, ответные
сообщения в очередь порта завершения не помещаются. */
while(_fgetts(Response.Record, MAX_RQRS_LEN, fp) != NULL) {
WriteFile(Key [KeyIndex].hNp, &Response, RS_SIZE, &nXfer, &ovResp);
WaitForSingleObject(hWrEvent, INFINITE);
}
fclose(fp);
/* Уничтожить содержимое временного файла. */
SetFilePointer(hTmpFile, 0, NULL, FILE_BEGIN);
SetEndOfFile(hTmpFile);
/* Отправить признак конца ответа. */
Response.Status = 1;
strcpy(Response.Record, "");
WriteFile(Key[KeyIndex].hNp, &Response, RS_SIZE, &nXfer, &ovResp);
WaitForSingleObject(hWrEvent, INFINITE);
/* Конец основного командного цикла. Получить следующую команду.*/
Disconnect = !ReadFile(Key[KeyIndex].hNp, &Key[KeyIndex].Req, RQ_SIZE, &nXfer, &Key[KeyIndex].Ov) && GetLastError == ERROR_HANDLE_EOF; /* Следующее чтение */
if (Disconnect) continue;
Success = TRUE;
}
} __finally {
if (Disconnect) {
/* Создать еще одно соединение по этому каналу. */
Key[KeyIndex].Type = 0;
DisconnectNamedPipe(Key[KeyIndex].hNp);
ConnectNamedPipe(Key[KeyIndex].hNp, &Key[KeyIndex].Ov);
}
if (!Success) {
ReportError(_T("Ошибка сервера"), 0, TRUE);
Exit = TRUE;
}
}
FlushFileBuffers(Key[KeyIndex].hNp);
DisconnectNamedPipe(Key[KeyIndex].hNp);
CloseHandle(hTmpFile);
/* … */
_endthreadex(0);
return 0;
/* Подавление предупреждающих сообщений компилятора. */
}
Резюме
Для выполнения асинхронных операций ввода/вывода в Windows предусмотрены три метода. Самой распространенной и наиболее простой является методика, основанная на использовании потоков, которая, в отличие от двух остальных, способна работать даже под управлением Windows 9x. Каждый из потоков отвечает за выполнение определенной последовательности действий, состоящей из одной или нескольких последовательно выполняющихся, блокирующихся операций ввода/вывода. Кроме того, каждый поток должен располагать собственным дескриптором файла или канала.
Поделиться:
Популярные книги
Сын Тишайшего
1. Царь Федя
Фантастика:
попаданцы
альтернативная история
фэнтези
5.20
рейтинг книги
"Искажающие реальность" Компиляция. Книги 1-14
Искажающие реальность
Фантастика:
боевая фантастика
космическая фантастика
киберпанк
рпг
5.00
рейтинг книги
Школа. Первый пояс
2. Путь
Фантастика:
фэнтези
7.67
рейтинг книги
Невеста на откуп
2. Невеста на откуп
Фантастика:
фэнтези
5.83
рейтинг книги
Убивать чтобы жить 2
2. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Вперед в прошлое!
1. Вперед в прошлое
Фантастика:
попаданцы
5.00
рейтинг книги
Аргумент барона Бронина 4
4. Аргумент барона Бронина
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Измена. (Не)любимая жена олигарха
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Право на обман
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Бастард Императора. Том 7
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Жаба с кошельком
19. Любительница частного сыска Даша Васильева
Детективы:
иронические детективы
8.26
рейтинг книги
Бастард Императора. Том 11
11. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Академия чаросвет. Тень
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Наследие Маозари 4
4. Наследие Маозари
Фантастика:
фэнтези
попаданцы
5.00