Пожалуйста, выделяйте текст программы тегом [сode=pas] . [/сode] . Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля. Указывайте точные версии Delphi и используемых сетевых библиотек.
Не приветствуется поднятие старых тем. Если ваш вопрос перекликается со старой темой, то для вопроса лучше создать новую тему, а старую указать в первом сообщении с описанием взаимосвязи. Внимание: попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней. Повторная попытка — 60 дней. Последующие попытки бан. Мат в разделе — бан на три месяца. Полезные ссылки: MSDN Library FAQ раздела Поиск по разделу Как правильно задавать вопросы
Выразить свое отношение к модераторам раздела можно здесь: Krid, Rouse_
Rouse_
Когда то давно я уже обьяснял — чтож, повторюсь пожалуй
Блокирующий режим: Как видно из названия, все операции, производимые с сокетом в момент установленного соединения, являются синхронными основному потоку приложения, из-за чего при вызове любой функции (отвечающих за передачу, прием данных или (в некоторых случаях) контроль состояния сокета), продолжение работы приложения приостанавливается дотехпор, пока функция не вернет результат. Чем отличается применение данного режима в приложении? Данный режим транспорта обычно применим, когда нужно приостановить работу приложения до окончательного получения данных, т.н. линейное программирование. Обычно вся работа с данным режимом сокета выносится с отдельный поток, во избежания остановки ЦВС главного приложения. Чаще всего данный тип транспорта применяется в консольных приложением, так как не имеет событий, связанных с обменом данных. Заметь работа серверного сокета без потоков практически невозможна — поэтому в TServerSocket используется stThreadBlocking.
Неблокирующий режим: В данном режиме выполнение операций с сокетом не приостанавливает работу приложения. О завершении работы функций приложение уведомляется. Данный режим реализован как альтернатива блокирующему режиму в потоке (т.е. при данном режиме поток попросту бесполезен). Так как уведомление о завершении выполнения приходило позже, то для реализациии получения данного уведомления, программист должен был озаботится о механизме — который и будет принимать данное уведомления. Вот тут уже и начинаются понятия ООП, такие как события (OnWrite, OnRead и т.д.).
Какой из режимов применять, каждый выбирает по себе. Не хочешь работать с потоками — работай с семафорами (Event). Не хочешь работать с ними — тогда работай через потоки
Я обычно придерживаюсь Winsock расширения сокетов Беркли под названием «Асинхронный режим сетевого транспорта». Данный вариант представляет из себя тотже неблокирующий режим, но отличие его от классического в том, что не нужно озаботится о механизме получения уведомлений. Данную часть на себя берет сама операционная система и именно она и будет оповещать тебя о произошедшем событии, посредством отправки оконных сообщений твоему приложению которые тебе нужно будет обработать (банальный SendMessage вызываемый с ее стороны)
2.1.15. Неблокирующий режим
2.1.15. Неблокирующий режим
Ранее мы столкнулись с функциями, которые могут надолго приостановить работу вызвавшей их нити, если действие не может быть выполнено немедленно. Это функции accept, recv, recvfrom, send, sendto и connect (в дальнейшем в этом разделе мы не будем упоминать функции recvfrom и sendto, потому что они в смысле блокирования эквивалентны функциям recv и send соответственно, и все, что будет здесь сказано о recv и send, применимо к recvfrom и sendto). Такое поведение не всегда удобно вызывающей программе, поэтому в библиотеке сокетов предусмотрен особый режим работы сокетов — неблокирующий. Этот режим может быть установлен или отменен дм каждого сокета индивидуально с помощью функции ioctlsocket, имеющей следующий прототип:
function ioctlsocket(s: TSocket; cmd: DWORD; var arg: u_long): Integer;
Данная функция предназначена для выполнения нескольких логически мало связанных между собой действий. Возможно, у разработчиков первых версий библиотеки сокетов были причины экономить на количестве функций, потому что мы и дальше увидим, что иногда непохожие операции выполняются одной функцией. Но вернемся к ioctlsocket. Ее параметр cmd определяет действие, которое выполняет функция, а также смысл параметра arg. Допустимы три значения параметра cmd: SIOCATMARK, FIONREAD и FIONBIO. При задании SIOCATMARK параметр arg рассматривается как выходной: в нем возвращается ноль, если во входном буфере сокета имеются высокоприоритетные данные, и ненулевое значение, если таких данных нет (как уже было оговорено, мы в этой книге не будем касаться передачи высокоприоритетных данных).
При cmd, равном FIONREAD, в параметре arg возвращается размер данных, находящихся во входном буфере сокета, в байтах. При использовании TCP это число равно максимальному количеству информации, которое можно получить на данный момент за один вызов recv. Для UDP это значение равно суммарному размеру всех находящихся в буфере дейтаграмм (напомним, что прочитать несколько дейтаграмм за один вызов recv нельзя). Функция ioctlsocket с параметром FIONREAD может использоваться для проверки наличия данных с целью избежать вызова recv тогда, когда это может привести к блокированию, или для организации вызова recv в цикле до тех пор, пока из буфера не будет извлечена вся информация.
При задании аргумента FIONBIO параметр arg рассматривается как входной. Если его значение равно нулю, сокет будет переведен в блокирующий режим, если не равно нулю — в неблокирующий. Таким образом, чтобы перевести который сокет s в неблокирующий режим, нужно выполнить следующие действия (листинг 2.28).
Листинг 2.28. Перевод сокета в неблокирующий режим
ioctlsocket(S, FIONBIO, Arg);
Пока программа использует только стандартные сокеты (а не сокеты Windows), сокет может быть переведен в неблокирующий или обратно в блокирующий режим в любой момент. Неблокирующим может быть сделан любой сокет (серверный или клиентский) независимо от протокола.
Функция ioctlsocket возвращает нулевое значение в случае успеха и ненулевое — при ошибке. В примере, как всегда, проверка результата для краткости опущена.
Итак, по умолчанию сокет работает в блокирующем режиме. С особенностями работы функций accept, connect, recv и send в этом режиме мы уже познакомились. Теперь рассмотрим то, как они ведут себя в неблокирующем режиме. Для этого сначала вспомним, когда эти функции блокируют вызвавшую их нить.
? accept — блокирует нить, если на момент ее вызова очередь подключений пуста.
? connect — в случае TCP блокирует сокет практически всегда, потому что требуется время на установление связи с удаленным сокетом. Без блокирования вызов connect выполняется только в том случае, если какая-либо ошибка не дает возможности приступить к операции установления связи. Также без блокирования функция connect выполняется при использовании UDP, потому что в данном случае она только устанавливает фильтр для адресов.
? recv — блокирует нить, если на момент вызова входной буфер сокета пуст.
? send — блокирует нить, если в выходном буфере сокета недостаточно места, чтобы скопировать туда переданную информацию.
Если условия, при которых эти функции выполняются без блокирования, выполнены, то их поведение в блокирующем и неблокирующем режимах идентично. Если же выполнение операции без блокирования невозможно, функции возвращают результат, указывающий на ошибку. Чтобы понять, произошла ли ошибка из-за необходимости блокирования или из-за чего-либо еще. программа должна вызвать функцию WSAGetLastError. Если она вернет WSAEWOULDBLOCK, значит, никакой ошибки не было, но выполнение операции без блокирования невозможно. Закрывать сокет и создавать новый после WSAEWOULDBLOCK, разумеется, не нужно, т. к. ошибки не было, и связь (в случае TCP) осталась неразорванной.
Следует отметить, что при нулевом выходном буфере сокета (т. е. когда функция send передаст данные напрямую в сеть) и большом объеме информации функция send может выполняться достаточно долго, т. к. эти данные отправляются по частям, и на каждую часть в рамках протокола TCP получаются подтверждения. Но эта задержка не считается блокированием, и в данном случае send будет одинаково вести себя с блокирующими и неблокирующими сокетами, т. е. вернет управление программе лишь после того, как все данные окажутся в сети.
Для функций accept, recv и send WSAEWOULDBLOCK означает, что операцию следует повторить через некоторое время, и, может быть, в следующий раз она не потребует блокирования и будет выполнена. Функция connect в этом случае начинает фоновую работу по установлению соединения. О завершении этой работы можно судить по готовности сокета, которая проверяется с помощью функции select. Листинг 2.29 иллюстрирует это.
Листинг 2.29. Установление связи при использовании неблокирующего сокета
SetW, SetE: TFDSet;
S:=socket(AF_INET, SOCK_STREAM, 0);
ioctlsocket(S, FIONBIO, Block);
if WSAGetLastError <> WSAEWOULDBLOCK then
select(0, nil, @SetW, @SetE, nil);
if FD_ISSET(S, SetW) then
// Connect выполнен успешно
else if FD_ISSET(S, SetE) then
// Соединиться не удалось
// Произошла еще какая-то ошибка
Напомним, что сокет, входящий в множество SetW, будет считаться готовым, если он соединен, а в его выходном буфере есть место. Сокет, входящий в множество SetE, будет считаться готовым, если попытка соединения не удалась. До тех пор, пока попытка соединения не завершилась (успехом или неудачей), ни одно из этих условий готовности не будет выполнено. Таким образом, в данном случае select завершит работу только после того, как будет выполнена попытка соединения, и о результатах этой попытки можно будет судить по тому, в какое из множеств входит сокет.
Из приведенного примера не видно, какие преимущества дает неблокирующий сокет по сравнению с блокирующим. Казалось бы, проще вызвать connect в блокирующем режиме, дождаться результата и лишь потом переводить сокет в неблокирующий режим. Во многих случаях это действительно может оказаться удобнее. Преимущества соединения в неблокирующем режиме связаны с тем, что между вызовами connect и select программа может выполнить какую-либо полезную работу, а в случае блокирующего сокета программа будет вынуждена сначала дождаться завершения работы функции connect и лишь потом сделать что-то еще.
Функция send для неблокирующего сокета также имеет некоторые специфические черты поведения. Они проявляются, когда свободное место в выходном буфере есть, но его недостаточно для хранения данных, которые программа пытается отправить с помощью этой функции. В этом случае функция send, согласно документации, может скопировать в выходной буфер такой объем данных, для которого хватает места. При этом она вернет значение, равное этому объему (оно будет меньше, чем значение параметра len, заданного программой). Оставшиеся данные программа должна отправить позже, вызвав еще раз функцию send. Такое поведение функции send возможно только при использовании TCP. В случае UDP дейтаграмма никогда не разделяется на части, и если в выходном буфере не хватает места для всей дейтаграммы, то функция send возвращает ошибку, a WSAGetLastError — WSAEWOULDBLOCK.
Сразу отметим, что, хотя спецификация допускает частичное копирование функцией send данных в буфер сокета, на практике такое поведение наблюдать пока не удалось: все эксперименты показали, что функция send всегда либо копирует данные целиком, расширяя при необходимости буфер, либо дает ошибку WSAEWOULDBLOCK. Далее этот вопрос будет обсуждаться подробнее. Тем не менее при написании программ следует учитывать возможность частичного копирования, т. к. оно может появиться в тех условиях или в тех реализациях библиотеки сокетов, которые в наших экспериментах не были проверены.
Данный текст является ознакомительным фрагментом.
Продолжение на ЛитРес
Читайте также
9.4.3.4. Неблокирующий ввод/вывод для каналов и FIFO
9.4.3.4. Неблокирующий ввод/вывод для каналов и FIFO Ранее для описания способа работы каналов мы использовали сравнение с двумя людьми, моющими и вытирающими тарелки с использованием сушилки; когда сушилка заполняется, останавливается моющий, а когда она пустеет,
Пользовательский режим и режим ядра
Пользовательский режим и режим ядра Сервер NFS в основном предназначен для обмена данными между файлами на диске и сетевым интерфейсом. В обычных условиях сервер NFS выполняется в системе Linux в пользовательском режиме. Это означает, что сервер не имеет специальных
Режим чтения
Режим чтения Режим чтения был создан для того, чтобы пользователи могли свободно читать и перемещаться по документу, не распечатывая его (рис. 2.55). Название этого режима говорит само за себя – в нем удобнее всего работать с документом, если нужно подробно изучить то, что в
Интерактивный режим
Интерактивный режим Интерактивная утилита isql может быть запущена локально или с удаленного клиента.* Для запуска isql с удаленного клиента всегда требуются имя пользователя и пароль.* Если вы соединены локально, вы можете установить переменные операционной системы ISC_USER и
Командный режим
Командный режим Хотя isql имеет некоторые удобные интерактивные возможности, она не ограничена только этим режимом. Многие интерактивные команды доступны также в виде переключателей командной строки. Некоторые функции isql, такие как извлечение метаданных, доступны только
Режим дизайна
Режим дизайна Система ArCon предназначена не только для строительных проектов, но и для оформления и визуализации интерьера помещений. Это вторая составляющая программы, реализованная через специальный режим – режим дизайна.При построении дома вы не должны сначала
23.4. Режим восстановления
23.4. Режим восстановления Режим восстановления позволяет получить права root без входа в систему. Просто выберите в меню GRUB2 (рис. 23.2) пункт: Ubuntu, kernel 2.6.32-16-generic (режим восстановления) Совет Если вы вообще не видите меню загрузчика GRUB2, тогда вернитесь к главе 19, в которой
Режим захвата
Режим захвата Перед описанием непосредственно процесса захвата стоит подробно рассказать об особенностях использования Pinnacle Studio в режиме
Режим Сценарий
Режим Сценарий Итак, режим Сценарий лучше всего подходит для задания или проверки последовательности сцен, из которых составляется фильм проекта. Каждая сцена в этом режиме представлена кадром на киноленте. Кроме сцен в кадрах ленты могут быть показаны титры и меню. Как
Режим Num Lock
Режим Num Lock При входе пользователя в систему режим Num Lock по умолчанию выключен. Однако с помощью реестра можно сделать так, что по умолчанию этот режим будет включен. Для этого необходимо в разделе реестра HKEY_USERS.DEFAULTControl PanelKeyboard присвоить строковому параметру InitialKeyboardIndicators
Режим исправлений
Режим исправлений Второй важной возможностью, которая предоставляется текстовым редактором Word, является работа в режиме исправлений. Основным его отличием от обычного режима редактирования текста является возможность сохранения всех вносимых исправлений. Причем это
Режим ПК
Режим ПК Данный режим предназначен не только для работы с документами MS Office: MS Word, MS Excel, MS PowerPoint, но и с любыми другими программами, установленными на ПК. Все изменения, произведенные в этом режиме, могут быть сохранены в исходном файле и формате документа, как отдельный
Режим экрана ПК
Режим экрана ПК В режиме экрана ПК (рис. 8.1) маркер интерактивной доски работает аналогично компьютерной мыши. С его помощью можно запускать любые программы, установленные на компьютере, работать в любых приложениях. Поддерживается двойной щелчок мыши и функция
Программный режим
Программный режим Обозначается буквой Р. Это, в общем-то, автоматический режим, но в отличие от Авто он позволяет вам вносить свои изменения во многие выбранные камерой параметры: менять светочувствительность ISO, баланс белого, выбрать режим и точку автофокусировки,