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

 pBuffer = message + p->static_buf_len;

 p->static_buf_len = 0;

 while (nRemainRecv > 0 && !Disconnect) {

  nXfer = recv(sd, TempBuf, nRemainRecv, 0);

  if (nXfer <= 0) {

   Disconnect = TRUE;

   continue;

  }

  nRemainRecv –= nXfer;

  /* Передать в целевое сообщение все символы вплоть до нулевого, если таковой имеется. */

  for (k =0; k < nXfer && TempBuf[k] != '\0'; k++) {

   *pBuffer = TempBuf[k];

   pBuffer++;

  }

  if (k >= nXfer) { /*Признак конца строки не обнаружен, читать дальше*/

   nRemainRecv –= nXfer;

  } else { /* Обнаружен признак конца строки. */

   *pBuffer = '\0';

   nRemainRecv = 0;

   memcpy(p->static_buf, &TempBuf[k + 1], nXfer – k – 1);

   p->static_buf_len = nXfer – k – 1;

  }

 }

 return Disconnect;

}

_declspec(dllexport)

BOOL SendCSMessage(RESPONSE *pResponse, SOCKET sd) {

 /* Послать запрос серверу в сокет sd. */

 BOOL Disconnect = FALSE;

 LONG32 nRemainSend, nXfer;

 LPSTR pBuffer; 

 pBuffer = pResponse->Record;

 nRemainSend = strlen(pBuffer) + 1;

 while (nRemainSend > 0 && !Disconnect) {

  /* Отправка еще не гарантирует, что будет отослано все сообщение. */

  nXfer = send(sd, pBuffer, nRemainSend, 0);

  if (nXfer <= 0) {

   fprintf(stderr, "\nОтключение сервера до посылки запроса завершения");

   Disconnect = TRUE;

  }

  nRemainSend –=nXfer;

  pBuffer += nXfer;

 }

 return Disconnect;

} 

<p>Комментарии по поводу DLL и безопасной многопоточной среды</p>

• Всякий раз, когда создается новый поток, вызывается функция DllMain с опцией DLL_THREAD_ATTACH, но для основного потока отдельного вызова с опцией DLL_THREAD_ATTACH не существует. В случае основного потока должна использоваться опция DLL_PROCESS_ATTACH.

• Вообще говоря, в том числе и в данном случае (возьмите, например, поток, принимающий сообщения (accept thread)), некоторым потокам распределение памяти может и не требоваться, но DllMain не в состоянии различать отдельные типы потоков. Поэтому на участке кода, соответствующем варианту выбора DLL_THREAD_ATTACH, фактического распределения памяти не происходит; здесь только инициализируется параметр TLS. Распределение памяти осуществляется точкой входа ReceiveCSMessage при первом ее вызове. Благодаря этому собственная память выделяется только тем потокам, которые в этом действительно нуждаются, и различные типы потоков получают ровно столько ресурсов, сколько им требуется.

• Хотя рассматриваемая библиотека DLL и обеспечивает безопасную многопоточную поддержку, любой поток в каждый момент времени может работать только с одним сокетом, поскольку долговременные состояния ассоциируются не с сокетами, а с потоками. Этот момент учитывается в следующем примере.

• Исходным кодом DLL, размещенным на Web-сайте, предусмотрен вывод общего количества вызовов DllMain в соответствии с их типами.

• Даже при таком решении существует риск утечки ресурсов. Некоторые потоки, например поток приема сообщений, могут вообще не завершаться, и поэтому не будут отсоединены от библиотеки DLL. Для остающихся активных потоков функция ExitProcess вызовет DllMain с опцией DLL_PROCESS_DETACH, а не DLL_THREAD_DETACH. В данном случае никаких проблем не возникает, поскольку поток приема сообщений никаких ресурсов не распределяет, а освобождение памяти происходит по завершении процесса. Однако, проблемы возможны в тех случаях, когда потоки распределяют такие ресурсы, как временные файлы. Поэтому окончательное решение должно предусматривать создание глобально доступного списка ресурсов. Тогда участок кода, соответствующий опции DLL_PROCESS_DETACH, мог бы взять на себя просмотр этого списка и освобождение ненужных ресурсов.

<p>Пример: альтернативная стратегия создания безопасных библиотек DLL с много поточной поддержкой</p>
Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
1001 совет по обустройству компьютера
1001 совет по обустройству компьютера

В книге собраны и обобщены советы по решению различных проблем, которые рано или поздно возникают при эксплуатации как экономичных нетбуков, так и современных настольных моделей. Все приведенные рецепты опробованы на практике и разбиты по темам: аппаратные средства персональных компьютеров, компьютерные сети и подключение к Интернету, установка, настройка и ремонт ОС Windows, работа в Интернете, защита от вирусов. Рассмотрены не только готовые решения внезапно возникающих проблем, но и ответы на многие вопросы, которые возникают еще до покупки компьютера. Приведен необходимый минимум технических сведений, позволяющий принять осознанное решение.Компакт-диск прилагается только к печатному изданию книги.

Юрий Всеволодович Ревич

Программирование, программы, базы данных / Интернет / Компьютерное «железо» / ОС и Сети / Программное обеспечение / Книги по IT