function WSAStartup(wVersionRequired: Word; var WSData: TWSAData): Integer;
Параметр
wVersionRequired
задает требуемую версию библиотеки сокетов. Младший байт задает основную версию, старший — дополнительную. Допустимы версии 1.0 ($0001), 1.1 ($0101), 2.0 ($0002) и 2.2 ($0202). Пока мы работаем со стандартными сокетами, принципиальной разницы между этими версиями нет, но версии 2.0 и выше пока лучше не использовать, т.к. модуль
WinSock
не рассчитан на их поддержку. Вопросы взаимоотношения библиотек и версий будут рассматриваться во втором разделе этой
главы, а пока ограничимся версией 1.1.
Параметр
WSData
выходной, т.е. значение, которое имела переменная до вызова функции, игнорируется, а имеет смысл только то значение, которое эта переменная получит после вызова функции. Через этот параметр передается дополнительная информация о библиотеке сокетов. В большинстве случаев эти сведения не представляют никакого интереса, поэтому их можно игнорировать.
Нулевое значение, возвращаемое функцией, говорит об успешном завершении, в противном случае возвращается код ошибки. Обычно функция, завершившаяся с ошибкой, возвращает значение
SOCKET_ERROR
.
Функция
WSACleanup
завершает работу с библиотекой сокетов. Эта функция не имеет параметров и возвращает ноль в случае успешного завершения или код ошибки в противном случае. Функцию
WSAStartup
достаточно вызвать один раз, даже в многонитевом приложении, в этом ее отличие от таких функций, как, например,
CoInitialize
, которая должна быть вызвана в каждой нити, использующей COM. Функцию можно вызывать повторно — в этом случае ее вызов не дает никакого эффекта, но для завершения работы с библиотекой сокетов функция
WSACleanup
должна быть вызвана столько же раз, сколько была вызвана
WSAStartup
.
Большинство функций библиотеки сокетов возвращают значение, позволяющее судить только об успешном или неуспешном завершении операции, но не дающее информации о том, какая именно ошибка произошла (если она произошла). Для получения сведений об ошибке служит функция
WSAGetLastError
, не имеющая параметров и возвращающая целочисленный код последней ошибки, произошедшей в библиотеке сокетов в данной нити. После неудачного завершения функции из библиотеки сокетов следует вызывать функцию
WSAGetLastError
, чтобы выяснить причину неудачи.
Забегая чуть вперед, отметим, что библиотека сокетов содержит стандартную функцию
getsockopt
, которая, кроме всего прочего, также позволяет получить информацию об ошибке. Однако она менее удобна, поэтому в тех случаях, когда не требуется совместимость с другими платформами, лучше прибегнуть к
WSAGetLastError
. К тому же,
getsockopt
возвращает ошибку, связанную с указанным сокетом, поэтому с её помощью нельзя получить код ошибки, не связанной с конкретным сокетом.
Для создания сокета предусмотрена стандартная функция
socket
со следующим прототипом:
function socket(af, struct, protocol: Integer): TSocket;
Параметр
аf
задаёт семейство адресов (address family). Этот параметр определяет, какой способ адресации (т.е. по сути дела, какой стек протоколов) будет использоваться для данного сокета. Для TCP/IP этот параметр должен быть равен
AF_INET
,
для других стеков также есть соответствующие константы, которые можно посмотреть в файле WinSock.pas.
Параметр
struct
указывает тип сокета и может принимать одно из двух значений:
SOCK_STREAM
(для потоковых протоколов) и
SOCK_DGRAM
(для дейтаграммных протоколов).
Параметр
protocol
позволяет указать, какой именно протокол будет использоваться сокетом. Этот параметр можно оставить равным нулю — тогда будет выбран протокол по умолчанию, отвечающий условиям, заданным первыми двумя параметрами. Для стека TCP/IP потоковый протокол по умолчанию — TCP, дейтаграммный — UDP. В некоторых примерах можно увидеть значение третьего параметра равно
IPPROTO_IP
. Значение этой константы равно 0, и ее использование только повышает читабельность кода, но приводит к тому же результату: будет выбран протокол по умолчанию. Если требуется протокол, отличный от протокола по умолчанию (например, в некоторых реализациях стека TCP/IP существует протокол RDP — Reliable Datagram Protocol, надежный дейтаграммный протокол), следует указать здесь соответствующую константу (для RDP это будет
IPPROTO_RDP
). Можно также явно задать TCP или UDP с помощью констант
IPPROTO_TCP
и
IPPROTO_UDP
соответственно.
Тип
TSocket
предназначен для хранения дескриптора сокета. Формально он совпадает с 32-битным беззнаковым целым типом, но об этом лучше не вспоминать, т.к. любые операции над значениями типа
TSocket
бессмысленны. Значение, возвращаемое функцией
socket
, следует сохранить в переменной соответствующего типа и затем использовать для идентификации сокета при вызове других функций. Если по каким-то причинам создание сокета невозможно, функция вернет значение
INVALID_SOCKET
. Причину ошибки можно узнать с помощью функции
WSAGetLastError
.
Сокет, созданный с помощью функции
socket
, не привязан ни к какому адресу. Привязка осуществляется с помощью функции
bind
, имеющей следующий прототип:
function bind(s: TSocket; var addr: TSockAddr; namelen: Integer): Integer;
Первый параметр этой функции — дескриптор сокета. который привязывается к адресу. Здесь, как и в остальных подобных случаях, требуется передать значение, которое вернула функция
socket
. Второй параметр содержит адрес, к которому требуется привязать сокет, а третий — длину структуры, содержащей адрес.
Функция
bind
предназначена для сокетов, реализующих разные протоколы из разных стеков, поэтому кодирование адреса в ней сделано достаточно универсальным. Впрочем, следует отметить, что разработчики модуля
WinSock
для Delphi выбрали не лучший способ перевода прототипа этой функции на Паскаль, поэтому универсальность в значительной мере утрачена. В оригинале прототип функции
bind
имеет следующий вид:
int bind(SOCKET s, const struct sockaddr FAR* name, int namelen);