Протокол TCP работает по технологии клиент-сервер. Чтобы обмениваться данными, сначала два компьютера должны установить соединение. Для этого один из них начинает прослушивание на определенном порте (такой компьютер называется сервером). После этого второй компьютер (клиент) может присоединиться к серверу.

Давайте рассмотрим функции, необходимые для создания сервера. Сначала мы должны связать локальный сетевой адрес с сокетом Для этого используется функция bind. Она описывается следующим образом:

function bind(
s: TSocket:
var addr: TSockAddr;
namelen: Integer ): Integer;
stdcall;
Функция bind имеет следующие параметры: • s - предварительно созданный сокет;
в addi- указатель на структуру типа SockAddr. Тип этой структуры зависит от используемой адресации (протокола);

в name! en - размер структуры SockAddr, указанной в качестве второго параметра.

Если функция отработала удачно, то результатом будет 0 в противном случае возвращается значение S0CKETERR0R. Код ошибки можно получить с помощью функции WSAGetLastError Возможны следующие ошибки:

• WSANOTINITIALISED - сначала необходимо вызвать функцию WSASturtup, а потом создавать сокет;
• WSAENETDOWN - связь нарушена, возможные причины - отошел кабель или произошло отключение от Интернета;
• WSAEADDRINUSE - указанный адрес уже используется;
• WSAEFAULT - параметры name и name! en не соответствуют выбранной адресации. Параметр namelen может быть меньше необходимого значения, a name может содержать некорректные данные;
• WSAEINPROGRESS - выполняется операция в блокирующем режиме. Вы уже запустили на выполнение какую-то функцию и нужно дождаться завершения ее работы;
• WSAEINVAL - сокет уже связан с адресом;
• WSAENOBUFS - недостаточно буферов, слишком много соединений;

• WSAEN0TS0CK - неверный дескриптор сокета.

Структура SockAddr может описываться по-разному, в зависимости от используемого протокола. Это связано с тем, что структура предназначена для хранения адреса, а в разных протоколах используется своя адресация. Для интернет-протоколов, таких как TCP и UDP, структура имеет имя SockAddrln (в данном случае "in" на конце является сокращением слова Internet, указывает на интернет-адресацию) и выглядит следующим образом:

SockAddr_In = record sin_family: u_short: sin_port: u_short: sin_addr: TInAddr;
sin_zero: array[0..7] of Char):
end;
TSockAddrln = sockaddrjin;

После объявления структуры описывается переменная TSockAddrln, ее рекомендуется использовать в Delphi при работе с интернет-адресом.

Рассмотрим параметры структуры SockAddrln:

• si n_f ami 1 у - семейство протоколов. Этот параметр схож с первым параметром функции socket. Мы будем использовать интернет-протоколы, поэтому здесь указана константа AF_INET. По этому параметру система определит, какие данные и в каком формате представлены в остальных параметрах структуры;
• sinport - порт, который будет применяться для идентификации нашей программы, когда к компьютеру поступят данные;
• sinaddr - структура SockAddrln, которая хранит IP-адрес;

• sinzero - выравнивание, с помощью которого размер структуры дополняется до определенного в системе значения.

Структура SockAddrln имеет и более короткий вариант записи:

SockAddrJn = record sa_family: u_short:

sa_data: аггау[0..13] of Char

end:

Здесь указываются только семейство протоколов и выравнивание, в котором все данные обнуляются.

Давайте сейчас подробнее остановимся на портах. Вы должны быть очень внимательны при выборе порта, потому что если на нем уже будет работать какая-то программа, то вторая попытка закончится ошибкой. Только одно приложение может работать с определенным портом. Открытые порты другим программам недоступны и не могут быть повторно открыты.

Вы должны знать, что некоторые порты зарезервированы для определенных (наиболее популярных) служб. Номера этих портов распределяются центром Internet Assigned Numbers Authority (IANA). Существует три категории портов:

в 0-1023 - управляются IANA и зарезервированы для стандартных служб. Не рекомендуется использовать порты из этого диапазона, потому что существует большая вероятность вступить в конфликт с другими программами;
в 1024-49151 - зарезервированы IANA, но могут использоваться процессами и программами. Большинство из этих портов можно использовать;

в 49152-65535 - частные порты и никем не зарезервированы. Эти порты используются в частных программах, и вероятность вступить в конфликт ничтожно мала.

Если во время выполнения функции bind выяснится, что порт уже используется какой-то службой, то функция возвратит ошибку WSAEADDRINUSE.

После того как локальный адрес и порт привязаны к сокету, мы можем приступить к прослушиванию порта в ожидании соединения со стороны клиента. Для этого служит функция 1 isten, которая описывается следующим образом:

function listen(
s: TSocket:
backlog: Integer ): Integer;
stdcall;

Первый параметр - это все тот же сокет, к которому привязали адрес. По этим данным функция определит, на каком порту нужно запустить прослушивание.

Второй параметр - это максимальная длина очереди запросов. Допустим, вы указали здесь значение 3, а вам пришло 5 запросов на соединение от разных клиентов. Только три первых из них встанут в очередь, а остальные получат ошибку WSAECONNREFUSED. Таким образом, при написании клиента, при попытке соединиться вы обязательно должны проверять, чтобы не было этой ошибки.

При вызове функции 1 isten вы можете получить следующие основные ошибки:

• WSANOTINITIALISED - сначала необходимо вызвать функцию WSASturtup, а потом создавать сокет;
• WSAENETD0WN - связь нарушена, возможные причины - отошел кабель или произошло отключение от Интернета;
в WSAEADDRINUSE - прослушивание уже запущено;
• WSAEINVAL - сокет не был связан функцией bind;
• WSAEINPROGRESS - выполняется операция в блокирующем режиме. Вы уже запустили на выполнение какую-то функцию и нужно дождаться завершения ее работы;
• WSAENOBUFS - недостаточно буферов, слишком много соединений;
• WSAEN0TS0CK - неверный дескриптор сокета;
• WSAEISCONN - сокет уже подключен;
• WSAEMFILE - больше нет доступных дескрипторов;

• WSAE0PN0TSUPP - указанный сокет не поддерживает функцию 1 і sten. Эта ошиб-1 ка возникает, когда выбран протокол без установки соединения, например

UDP, а вы пытаетесь вызвать функцию listen.

Когда клиент попадает в очередь на подключение к серверу, то мы должны разрешить соединение с помощью функции accept. Она описывается следующим образом:

function accepte
s: TSocket;
addr: PSockAddr;
addrlen: PInteger ): TSocket: stdcal1 :

Во второй версии есть функция WSAAccept, у которой первые три параметра такие же, как и у функции accept. Функция WSAAccept выглядит следующим образом:

SOCKET WSAAccept ( SOCKET s.
struct sockaddr FAR * addr. LPINT addrlen.
LPCONDITIONPROC lpfnCondition. DWORD dwCallbackData);

Если рассмотренные ранее функции, начинающиеся с префикса WSA, появились раньше (например, в версии 1.1), то эта доступна только в 2.0. Чтобы использовать ее возможности в своих проектах, нужно подключить модуль WinSock 2.

Приведу общие параметры для этих функций:

• предварительно созданный сокет, который мы запустили на прослушивание;
• указатель на структуру типа SockAddr;

• размер структуры SockAddr, указанной в качестве второго параметра.

После выполнения функции accept второй параметр (addr) будет содержать сведе-' ния об IP-адресе клиента, который произвел подключение. Эти данные используются для проверки, может ли клиент с таким адресом работать с сервером. Таким образом, очень просто реализовать контроль доступа по IP-адресу. Но вы должны знать, что злоумышленнику не составляет труда подделать IP-адрес, поэтому такую защиту нельзя назвать достаточной. Тем не менее процедура взлома сервера усложняется.

Функция accept возвращает указатель на новый сокет, который вы можете использовать для общения с клиентом. Старая переменная типа SOCKET продолжает прослушивать порт в ожидании новых соединений и использовать ее нет смысла. Таким образом, для каждого подключенного клиента будет свой SOCKET, благодаря чему вы сможете работать с любым их них.

Функция accept может генерировать следующие коды ошибок:

в WSANOTINITIALISED - сначала необходимо вызвать функцию WSASturtup, а потом создавать сокет;
в WSAENETDOWN - связь нарушена, возможные причины - отошел кабель или произошло отключение от Интернета;
в WSAEFAULT - параметр addrl en слишком маленький или параметр addr содержит не соответствующие выбранной адресации данные;
в WSAEINVAL - не была вызвана функция 1 i sten, прежде чем было принято соединение;
в WSAEINPROGRESS - выполняется операция в блокирующем режиме. Вы уже запустили на выполнение какую-то функцию и нужно дождаться завершения ее работы;
в WSAENOBUFS - недостаточно буферов, слишком много соединений;
в WSAEN0TS0CK - неверный дескриптор сокета;
в WSAEMFILE - очередь не пустая, но нет доступных дескрипторов;

в WSAE0PN0TSUPP - указанный сокет не может работать с установкой соединения.

4.4. Инициализация сети || Оглавление || 4.6. Функции клиента


Delphi в шутку и всерьез: что умеют хакеры



Новости за месяц

  • Январь
    2022
  • Пн
  • Вт
  • Ср
  • Чт
  • Пт
  • Сб
  • Вс