Читаем Системное программирование в среде Windows полностью

  CloseHandle(hAcceptTh);

  hAcceptTh = NULL; /* Подготовиться к следующему соединению. */

 }

 _tprintf(_T("Остановка сервера. Ожидание завершения всех потоков сервера\n"));

 /* Завершить принимающий поток, если он все еще выполняется. */

 /* Более подробная информация об используемой логике завершения */

 /* работы приведена на Web-сайте книги. */

 if (hDll != NULL) FreeLibrary(hDll);

 if (hAcceptTh != NULL) TerminateThread(hAcceptTh, 0);

 /* Ожидать завершения всех активных потоков сервера. */

 for (ith = 0; ith < MAXCLIENTS; ith++) if (srv_arg [ith].status != 0) {

  WaitForSingleObject(srv_arg[ith].srv_thd, INFINITE);

  CloseHandle(srv_arg[ith].srv_thd);

 }

 shutdown(SrvSock, 2);

 closesocket(SrvSock);

 WSACleanup;

 return 0;

}

static DWORD WINAPI AcceptTh(SERVER_ARG * pThArg) {

 /* Принимающий поток, который предоставляет основному потоку возможность опроса флага завершения. Кроме того, этот поток создает серверный поток. */

 LONG AddrLen, ThId;

 AddrLen = sizeof(ConnectSAddr);

 pThArg->sock = accept(SrvSock, /* Это блокирующий вызов. */

  (struct sockaddr *)&ConnectSAddr, &AddrLen);

 /* Новое соединение. Создать серверный поток. */

 pThArg->status = 2;

 pThArg->srv_thd = (HANDLE)_beginthreadex (NULL, 0, Server, pThArg, 0, &ThId);

 return 0; /* Серверный поток продолжает выполняться. */

}

static DWORD WINAPI Server(SERVER_ARG * pThArg)

/* Функция серверного потока. Поток создается по требованию. */

{

 /* Каждый поток поддерживает в стеке собственные структуры данных запроса, ответа и регистрационных записей. */

 /* … Стандартные объявления из serverNP опущены … */

 SOCKET ConnectSock; 

 int Disconnect = 0, i;

 int (*dl_addr)(char *, char *);

 char *ws = " \0\t\n"; /* Пробелы. */

 GetStartupInfo(&StartInfoCh);

 ConnectSock = pThArg->sock;

 /* Создать имя временного файла. */

 sprintf(TempFile, "%s%d%s", "ServerTemp", pThArg->number, ".tmp");

 while (!Done && !ShutFlag) { /* Основной командный цикл. */

  Disconnect = ReceiveRequestMessage(&Request, ConnectSock);

  Done = Disconnect || (strcmp(Request.Record, "$Quit") == 0) || (strcmp(Request.Record, "$ShutDownServer") == 0);

  if (Done) continue;

  /* Остановить этот поток по получении команды "$Quit" или "$ShutDownServer". */

  hTrapFile = CreateFile(TempFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &TempSA, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

  /* Проверка наличия этой команды в DLL. Для упрощения команды */

  /* разделяемой библиотеки имеют более высокий приоритет по сравнению */

  /* с командами процесса. Прежде всего, необходимо извлечь имя команды.*/

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже