Чтение онлайн

ЖАНРЫ

Системное программирование в среде Windows

Харт Джонсон М.

Шрифт:

/* Закрыть дескрипторы канала и удалить временные файлы. */

CloseHandle(hSrvrThread[iNp]);

DeleteFile(ThArgs[iNp].TmpFileName);

 }

 _tprintf(_T("Серверный процесс завершил выполнение.\n"));

 return 0;

}

static DWORD WINAPI Server(LPTHREAD_ARG pThArg)

/* Функция потока сервера; по одной для каждого потенциального
клиента. */

{

 HANDLE hNamedPipe, hTmpFile = INVALID_HANDLE_VALUE, hConTh, hClient;

 DWORD nXfer, ConThId, ConThStatus;

 STARTUPINFO StartInfoCh;

 SECURITY_ATTRIBUTES TempSA = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};

 PROCESS_INFORMATION ProcInfo;

 FILE *fp;

 REQUEST Request;

 RESPONSE Response;

 GetStartupInfo(&StartInfoCh);

 hNamedPipe = pThArg->hNamedPipe;

 hTmpFile = CreateFile(pThArg->TmpFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &TempSA, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);

 while (!ShutDown) { /* Цикл соединений. */

/* Создать поток соединения; ждать его завершения. */

hConTh = (HANDLE)_beginthreadex(NULL, 0, Connect, pThArg, 0, &ConThId);

/* Ожидание соединения с клиентом и проверка флага завершения работы.*/

while (!ShutDown && WaitForSingleObject(hConTh, CS_TIMEOUT) == WAIT_TIMEOUT) { /* Пустое тело цикла. */ }; 

CloseHandle(hConTh);

if (ShutDown) continue; /*Флаг может быть установлен любым потоком.*/

/* Соединение существует. */

while (!ShutDown && ReadFile(hNamedPipe, &Request, RQ_SIZE, &nXfer, NULL)) {

/* Получать новые команды до отсоединения клиента. */

ShutDown = ShutDown || (_tcscmp(Request.Record, ShutRqst) == 0);

if (ShutDown) continue; /* Проверяется на каждой итерации. */

/* Создать процесс для выполнения команды. */

StartInfoCh.hStdOutput = hTmpFile;

StartInfoCh.hStdError = hTmpFile;

StartInfoCh.hStdInput = GetStdHandle(STD_INPUT_HANDLE);

StartInfoCh.dwFlags = STARTF_USESTDHANDLES;

CreateProcess(NULL, Request.Record, NULL, NULL, TRUE, /* Унаследовать дескрипторы. */

0, NULL, NULL, &StartInfoCh, &ProcInfo);

/* Выполняется процесс сервера. */

CloseHandle(ProcInfo.hThread);

WaitForSingleObject(ProcInfo.hProcess, INFINITE);

CloseHandle(ProcInfo.hProcess);

/* Отвечать по одной
строке за один раз. Здесь удобно использовать функции библиотеки С для работы со строками. */

fp = _tfopen(pThArg->TmpFileName, _T("r"));

Response.Status = 0;

while(_fgetts(Response.Record, MAX_RQRS_LEN, fp) != NULL) WriteFile(hNamedPipe, &Response, RS_SIZE, &nXfer, NULL);

FlushFileBuffers(hNamedPipe);

fclose(fp);

/* Уничтожить содержимое временного файла. */

SetFilePointer(hTmpFile, 0, NULL, FILE_BEGIN);

SetEndOfFile(hTmpFile);

/* Отправить признак конца ответа. */

Response.Status = 1;

strcpy(Response.Record, "");

WriteFile(hNamedPipe, &Response, RS_SIZE, &nXfer, NULL);

}

/* Конец основного командного цикла. Получить следующую команду. */

/* Принудительно завершить выполнение потока, если он все еще активен.*/

GetExitCodeThread(hConTh, &ConThStatus);

if (ConThStatus == STILL_ACTIVE) {

hClient = CreateFile(SERVER_PIPE, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN EXISTING, FILE ATTRIBUTE NORMAL, NULL); 

if (hClient != INVALID_HANDLE_VALUE) CloseHandle (hClient);

WaitForSingleObject (hConTh, INFINITE);

}

/* Клиент отсоединился или имеется запрос останова. */

FlushFileBuffers(hNamedPipe);

DisconnectNamedPipe(hNamedPipe);

 }

 /* Конец командного цикла. Освободить ресурсы; выйти из потока. */

 if (hTmpFile != INVALID_HANDLE_VALUE) CloseHandle(hTmpFile);

 DeleteFile(pThArg->TmpFileName);

 _tprintf(_T("Выход из потока номер %d\n"), pThArg->ThreadNo);

 _endthreadex(0);

}

static DWORD WINAPI Connect(LPTHREAD_ARG pThArg) {

 /* Поток соединения разрешает серверу опрос флага ShutDown. */

 ConnectNamedPipe(pThArg->hNamedPipe, NULL);

 _endthreadex(0);

 return 0;

}

BOOL WINAPI Handler(DWORD CtrlEvent) {

 /* Завершить работу системы. */

 ShutDown = TRUE;

 return TRUE;

}

Комментарии по поводу клиент-серверного процессора командной строки

Поделиться с друзьями: