Джонсон Харт - Системное программирование в среде Windows
- Название:Системное программирование в среде Windows
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2005
- Город:Москва • Санкт-Петербург • Киев
- ISBN:5-8459-0879-5
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Джонсон Харт - Системное программирование в среде Windows краткое содержание
Эта книга посвящена вопросам разработки приложений с использованием интерфейса прикладного программирования операционных систем компании Microsoft (Windows 9х, Windows XP, Windows 2000 и Windows Server 2003). Основное внимание уделяется базовым системным службам, включая управление файловой системой, процессами и потоками, взаимодействие между процессами, сетевое программирование и синхронизацию. Рассматривается методика переноса приложений, написанных в среде Win32, в среду Win64. Подробно описываются все аспекты системы безопасности Windows и ее практического применения. Изобилие реальных примеров, доступных также и на Web-сайте книги, существенно упрощает усвоение материала.
Книга ориентирована на разработчиков и программистов, как высокой квалификации, так и начинающих, а также будет полезна для студентов соответствующих специальностей.
Системное программирование в среде Windows - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
/* SendReceiveSKHA.с – многопоточный потоковый сокет. */
/* Данная программа представляет собой модифицированную версию программы*/
/* SendReceiveSKST.c, которая иллюстрирует другую методику, основанную */
/* на безопасной библиотеке с многопоточной поддержкой. */
/* Состояние сохраняется не в TLS, а в структуре состояния, напоминающей*/
/* дескриптор HANDLE. Благодаря этому поток может использовать сразу */
/* несколько сокетов. Сообщения разделяются символами конца строки ('\0')*/
#define _NOEXCLUSIONS
#include "EvryThng.h"
#include "ClntSrvr.h " /* Определяет записи запроса и ответа. */
typedef struct SOCKET_HANDLE_T {
/* Текущее состояние сокета в структуре "handle". */
/* Структура содержит "static_buf_len" символов остаточных данных. */
/* Символы конца строки (нулевые символы) могут присутствовать, */
/* а могут и не присутствовать. */
SOCKET sk; /* Сокет, связанный с указанной структурой "handle". */
char static_buf[MAX_RQRS_LEN];
LONG32 static_buf_len;
} SOCKET_HANDLE, * PSOCKET_HANDLE;
/* Функции для создания и закрытия "дескрипторов потоковых сокетов". */
_declspec(dllexport)
PVOID CreateCSSocketHandle(SOCKET s) {
PVOID p;
PSOCKET_HANDLE ps;
p = malloc(sizeof(SOCKET_HANDLE));
if (p == NULL) return NULL;
ps = (PSOCKET_HANDLE)p;
ps->sk = s;
ps->static_buf_len = 0; /* Инициализировать состояние буфера. */
return p;
}
_declspec(dllexport)
BOOL CloseCSSocketHandle(PVOID p) {
if (p == NULL) return FALSE;
free(p);
return TRUE;
}
_declspec(dllexport)
BOOL ReceiveCSMessage(REQUEST *pRequest, PVOID sh)
/* Тип PVOID используется для того, чтобы избежать включения */
/* в вызывающую программу определения структуры SOCKET_HANDLE. */
{
/* Возвращаемое значение TRUE указывает на ошибку или отсоединение. … */
PSOCKET_HANDLE p;
SOCKET sd;
р = (PSOCKET_HANDLE)sh;
if (p == NULL) return FALSE;
sd = p->sk;
/* Этим исчерпываются все отличия от SendReceiveSKST! … */
}
_declspec(dllexport)
BOOL SendCSMessage(RESPONSE *pResponse, PVOID sh) {
/* Послать запрос серверу в сокет sd. … */
SOCKET sd;
PSOCKET_HANDLE p;
p = (PSOCKET_HANDLE)sh;
if (p == NULL) return FALSE;
sd = p->sk;
/* Этим исчерпываются все отличия от SendReceiveSKST! … */
}
Дейтаграммы
Дейтаграммы аналогичны почтовым ящикам и используются при сходных обстоятельствах. Соединение между отправителем и получателем отсутствует, а получателей может быть несколько. Ни почтовые ящики, ни дейтаграммы не гарантируют доставку данных получателю, а последовательные сообщения не обязательно будут получены в той же очередности, в которой они были отправлены.
Первым шагом при использовании дейтаграмм является создание сокета посредством вызова функции socket с указанием значения SOCK_DGRAM в поле type.
Далее необходимо использовать функции sendto и recvfrom, которые принимают те же аргументы, что и функции send и recv, но имеют по два дополнительных аргумента, относящихся к станции-партнеру. Так, функция sendto имеет следующий прототип:
int sendto(SOCKET s, LPSTR lpBuffer, int nBufferLen, int nFlags, LPSOCKADDR lpAddr, int nAddrLen);
lpAddr — указывает на адресную структуру, в которой вы можете задать имя конкретной системы и номер порта или же указать на необходимость рассылки дейтаграммы заданной совокупности систем.
Используя функцию recvfrom, вы указываете систему или системы (возможно, все), от которых вы хотите принимать дейтаграммы.
Использование дейтаграмм для удаленного вызова процедур
Обычно дейтаграммы применяются для реализации RPC. По сути дела, в самых распространенных ситуациях клиент посылает запрос серверу, используя дейтаграммы. Поскольку доставка запроса не гарантируется, клиент должен повторно передать запрос, если по истечении заданного периода ожидания ответ от сервера (для посылки которого также используются дейтаграммы) не получен. Сервер должен быть готов к тому, что один и тот же запрос может направляться ему несколько раз.
Важно отметить, что ни клиенту, ни серверу RPC служебные сигналы, которые, например, необходимы при образовании соединения через потоковый сокет, не требуются; вместо этого они связываются друг с другом посредством запросов и ответов. В качестве дополнительной возможности RPC может гарантировать надежность взаимодействия путем повторной передачи запросов по истечении периода ожидания, что упрощает разработку приложений. Выражаясь иначе, часто говорят о том, что клиент и сервер RPC не имеют состояния (они не хранят никакой информации относительно состояния текущего запроса или запросов, на которые еще не получен ответ). Отсюда следует, что результат обработки на сервере множества идентичных клиентских запросов будет тем же, что и результат обработки одиночного запроса. Это также значительно упрощает проектирование приложений и реализацию их логики.
Сравнение Berkeley Sockets и Windows Sockets
Программы, использующие стандартные вызовы Berkeley Sockets, будут работать и с Windows Sockets, если вы учтете следующие важные моменты:
• Для инициализации Winsock DLL вы должны вызвать функцию WSAStartup.
• Для закрытия сокета вы должны использовать не функцию close (которая является переносимой), а функцию closesocket (которая таковой не является).
• Для закрытия библиотеки DLL вы должны вызвать функцию WSACleanup.
При желании вы можете использовать типы данных Windows, например, SOCKET и LONG вместо int, как было сделано в этой главе. Программы 12.1 и 12.2 были перенесены из UNIX, и для этого потребовались самые минимальные усилия. Вместе с тем, потребовалось модифицировать DLL и разделы, осуществляющие управление процессами. В упражнении 12.13 вам предлагается перенести эти две программы обратно в UNIX.
Перекрывающийся ввод/вывод с использованием Windows Sockets
В главе 14 описывается асинхронный ввод/вывод, позволяющий потоку продолжать свое выполнение в процессе выполнения операции ввода/вывода. В той же главе обсуждается и совместное использование сокетов с асинхронным вводом/выводом Windows.
Большинство задач, связанных с программированием асинхронных операций, можно легко решить, применяя однотипный подход с использованием потоков. Так, в программе serverSK вместо неблокирующегося сокета используется принимающий поток (accept thread). Тем не менее, порты завершения ввода/вывода, связанные с асинхронным вводом/выводом, играют важную роль в обеспечении масштабируемости в случае большого количества клиентов. Эта тема также рассматривается в главе 14.
Windows Sockets 2
Версия Windows Sockets 2 вводит новые сферы функциональности и доступна на всех системах Windows, хотя системы Windows 9x требуют установки пакета обновления. В примерах использована версия 2.0, но можно применять и версию 1.1, если требуется совместимость с необновленными системами Windows 9х. Кроме того, возможностей версии 1.1 в большинстве случаев вам будет вполне достаточно. Версия Windows Sockets 2.0 обеспечивает, в частности, следующие возможности:
Читать дальшеИнтервал:
Закладка: