Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначенные для поддерживания проводов на необходимой высоте над землей, водой...
Поперечные профили набережных и береговой полосы: На городских территориях берегоукрепление проектируют с учетом технических и экономических требований, но особое значение придают эстетическим...
Топ:
Техника безопасности при работе на пароконвектомате: К обслуживанию пароконвектомата допускаются лица, прошедшие технический минимум по эксплуатации оборудования...
Процедура выполнения команд. Рабочий цикл процессора: Функционирование процессора в основном состоит из повторяющихся рабочих циклов, каждый из которых соответствует...
Устройство и оснащение процедурного кабинета: Решающая роль в обеспечении правильного лечения пациентов отводится процедурной медсестре...
Интересное:
Принципы управления денежными потоками: одним из методов контроля за состоянием денежной наличности является...
Как мы говорим и как мы слушаем: общение можно сравнить с огромным зонтиком, под которым скрыто все...
Наиболее распространенные виды рака: Раковая опухоль — это самостоятельное новообразование, которое может возникнуть и от повышенного давления...
Дисциплины:
2021-03-17 | 130 |
5.00
из
|
Заказать работу |
|
|
Принцип действия таких протоколов иной, так как в них используются другие методы отправки и приема данных. Обсудим сначала получателя (или сервер), потому что не требующий соединения приемник мало отличается от серверов, требующих соединения.
Приемник
Процесс получения данных на сокете, не требующем соединения, прост. Сначала создают сокет функцией socket. Затем выполняют привязку сокета к интерфейсу, на котором будут принимать данные, функцией bind (как и в случае протоколов, ориентированных на сеансы). Разница в том, что нельзя вызвать listen или accept: вместо этого нужно просто ожидать приема входящих данных. Поскольку в этом случае соединения нет, принимающий сокет может получать дейтаграммы от любой машины в сети. Простейшая функция приема — recvform:
int recvfrom(
SOCKET s,
char* buf,
int len
int flags,
struct sockaddr* from,
int* fromlen
);
Первые четыре параметра такие же, как и для функции recv, включают допустимые значения для flags: MSG_OOB и MSG_PEEK. Параметр from — структура SOCKADDR для данного протокола слушающего сокета, на размер структуры адреса ссылается fromlen. После возврата вызова структура SOCKADDR будет содержать адрес рабочей станции, которая отправляет данные.
Отправитель
Есть два способа отправки данных через сокет, не требующий соединения. Первый и самый простой — создать сокет и вызвать функцию sendto или WSASendTo. Рассмотрим сначала функцию sendto:
int sendto(
SOCKET s
const char* buf,
int len,
int flags,
const struct sockaddr * to,
int tolen
);
Параметры этой функции такие же, как и у recvfrom, за исключением buf— буфера данных для отправки, и len — показывающего сколько байт отправлять. Параметр to — указатель на структуру SOCKADDR с адресом принимающей рабочей станции.
|
Протоколы, ориентированные на передачу сообщений
Большинство протоколов, требующих соединения, — потоковые, а не требующих соединения — ориентированы на передачу сообщений. Поэтому при отправке и приеме данных нужно учесть ряд факторов. Во-первых, поскольку ориентированные на передачу сообщений протоколы сохраняют границы сообщений, данные, поставленные в очередь отправки, блокируются до завершения выполнения функции отправки. Если отправка не может быть завершена, при асинхронном или неблокирующем режиме ввода-вывода функция отправки вернет ошибку WSAEWOULDBLOCK. Это означает, что базовая система не смогла обработать данные и нужно попытаться вызвать функцию отправки повторно. Главное — в ориентированных на сообщения протоколах запись происходит только в результате самостоятельного действия.
Освобождение ресурсов сокета
Поскольку соединение не устанавливается, его формального разрыва или корректного закрытия не требуется. После прекращения отправки или получения данных отправителем или получателем просто вызывается функция closesocket с описателем требуемого сокета, в результате чего освобождаются все выделенные ему ресурсы.
Дополнительные функции API
Рассмотрим API-функции Winsock, которые пригодятся вам при создании сетевых приложений.
Функция getpeername
Эта функция возвращает информацию об адресе сокета партнера на подключенном сокете:
int getpeername(
SOCKET s,
struct sockaddr* name,
int* namelen
);
Первый параметр — сокет для соединения, два последних — указатель на структуру SOCKADDR базового протокола и ее длина. Для сокетов дейтаграмм данная функция возвращает адрес, переданный вызову соединения (за исключением адресов, переданных в вызов sendto).
Функция getsockname
Эта функция противоположна getpeername и возвращает адресную информацию для локального интерфейса определенного сокета:
int getsockname(
SOCKET s,
struct sockaddr* name,
int* namelen
);
Используются те же параметры, что и для getpeername, однако возвращается информация о локальном адресе. В случае TCP адрес совпадает с сокетой сервера, слушающим на заданном порте и IP-интерфейсе.
|
Ввод-вывод в Winsock
Эта глава посвящена управлению вводом-выводом через сокеты в Windows-приложениях. В Winsock такое управление реализовано с помощью режимов работы и моделей ввода-вывода. Режим (mode) сокета определяет поведение функций, работающих с сокетом. Модель (model) сокета описывает, как приложение производит ввод-вывод при работе с сокетом. Модели не зависят от режима работы и позволяют обходить их ограничения.
Winsock поддерживает два режима: блокирующий (blocking) и неблокирующий (nonblocking). Эти режимы подробно описаны в начале главы, здесь же демонстрируется их использование в приложениях для управления вводом-выводом. Далее приведен ряд интересных моделей, которые помогают приложению управлять несколькими сокетами одновременно в асинхронном режиме: select, WSAAsyncSelect, WSAEventSelect, перекрытый ввод-вывод (overlapped I/O) и порт завершения (completion port).
Режимы работы сокетов
В блокирующем режиме функции ввода-вывода, такие как send и recv, перед завершением ожидают окончания операции. В неблокирующем — работа функций завершается немедленно. Приложения, выполняемые на платформах Windows СЕ и Windows 95 (в случае Winsock 1), поддерживают очень мало моделей ввода-вывода и требуют от программиста описать блокирование и разблокирование сокетов в разных ситуациях.
Блокирующий режим
При блокировке сокета необходима осторожность, так как этом режиме любой вызов функции Winsock именно блокирует сокет на некоторое время. Большинство приложений Winsock следуют модели «поставщик — потребитель», в которой программа считывает или записывает определенное количество байт и затем выполняет с ними какие-либо операции.
SOCKET sock;
char buff[256];
int done = 0;
while(!done) {
nBytes = recv(sock, buff, 65);
if (nBytes == SOCKET_ERROR) {
printf("recv failed with error %d\n", WSAGetLastError());
return;
}
DoComputationOnData(buff);
}
Проблема в том, что функция recv может не завершиться никогда, так как для этого нужно считать какие-либо данные из буфера системы. В такой ситуации некоторые программисты могут соблазниться «подглядыванием» данных (чтение без удаления из буфера), используя флаг MSG_PEEK в recv или вызывая ioctlsocket с параметром FIONREAD. Подобный стиль программирования заслуживает резкой критики. Издержки, связанные с «подглядыванием», велики, так как необходимо сделать один или более системных вызовов для определения числа доступных байт, после чего все равно приходится вызывать recv для удаления данных из буфера.
|
Чтобы этого избежать, следует предотвратить замораживание приложения из-за недостатка данных (из-за сетевых проблем или проблем клиента) без постоянного «подглядывания» в системные сетевые буферы. Один из методов — разделить приложения на считывающий и вычисляющий потоки, совместно использующие общий буфер данных. Доступ к буферу регулируется синхронизирующим объектом, таким как событие или мьютекс. Задача считывающего потока — постоянно читать данные из сети и помещать их в общий буфер. Считав минимально необходимое количество данных, этот поток инициирует сигнальное событие, уведомляющее вычисляющий поток, что можно начинать вычисления. Затем вычисляющий поток удаляет часть данных из буфера и производит с ними необходимые операции. В следующем листинге реализованы две функции: для приема данных (ReadThread) и их обработки (ProcessThread).
// Перед созданием двух потоков,
// инициализируется общий буфер (data)
// и создается сигнальное событие (hEvent)
CRITICAL_SECTION data;
HANDLE hEvent;
TCHAR buff[MAX_BUFFER_SIZE];
int nbytes;
// Считывающий поток void ReadThread(void) {
int nTotal = 0, nRead = 0, nLeft = 0 nBytes = 0;
while (!done)
{
nTotal = 0;
nLeft = NUM_BYTES_REQUIRED;
while (nTotal!= NUM_BYTES_REQUIRED)
{
EnterCriticalSection(&data);
nRead = recv(sock, &(buff[MAX_BUFFER_SIZE - nBytes]), nLeft);
if (nRead == -1) {
printf("error\n"); ExitThread();
nTotal += nRead;
nLeft -= nRead;
nBytes += nRead;
LeaveCriticalSection(&data);
}
SetEvent(hEvent); } }
// Вычисляющий поток void ProcessThread(void)
WaitForSingleObject(hEvent);
EnterCriticalSection(&data);
DoSomeComputationOnData(buff);
// Удаление обработанных данных из буфера
// и сдвиг оставшихся в начало массива
nBytes -= NUM BYTES REQUIRED;
}
LeaveCriticalSection(&data);
}
Недостаток блокировки сокетов — приложению трудно поддерживать связь по нескольким сокетам одновременно. Приведенную схему можно изменить, чтобы считывающий и вычисляющий потоки создавались отдельно для каждого сокета. Для этого придется попотеть, зато вы получите более эффективное решение. Но учтите: данный вариант не предусматривает масштабирования, если вам придется работать с большим количеством сокетов.
|
Неблокирующий режим
Альтернатива описанному режиму — режим без блокировки. Он несколько сложнее в использовании, но обеспечивает те же возможности, что и режим блокировки, плюс некоторые преимущества. В следующем листинге показано, как создать сокет и перевести его в неблокирующий режим.
SOCKET s;
unsigned long ul = 1;
int nRet;
s = socket(AF_INET, SOCK_STREAM, 0);
nRet = ioctlsocket(s, FIOBIO, (unsigned long *)&ul);
if (nRet == SOCKET ERROR)
{
// Не удалось перевести сокет в неблокирующий режим
}
Если сокет находится в неблокирующем режиме, функции Winsock завершаются немедленно. В большинстве случаев они будут возвращать ошибку
|
|
Адаптации растений и животных к жизни в горах: Большое значение для жизни организмов в горах имеют степень расчленения, крутизна и экспозиционные различия склонов...
Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...
Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...
Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!