Первый параметр данной функции задаёт сокет, который служит для передачи данных. Здесь нужно указать значение, полученное ранее от функции socket
. Параметр Buf
задаёт буфер, в котором хранятся данные для отправки, а параметр len
— размер этих данных в байтах. Параметр flags
позволяет указать некоторые дополнительные опции, которых мы здесь касаться не будем, т.к. в большинстве случаев они не нужны. Пока следует запомнить, что параметр flags
в функции sendto
, а также в других функциях, где он встречается, должен быть равен нулю. Параметр addrto
задает адрес (состоящий из IP-адреса и порта) удаленного сокета, который должен получить эти данные. Значение параметра addrto
должно формироваться по тем же правилам, что значение аналогичного параметра функции bind, за исключением того, что IP-адрес и порт должны быть заданы явно (т.е. не допускаются значения INADDR_ANY
и нулевой номера порта). Параметр tolen
задает длину буфера, отведенного для адреса, и должен быть равен SizeOf(TSockAddr)
. Один вызов функции sendto
приводит к отправке одной дейтаграммы. Данные, переданные в sendto
, никогда не разбиваются на несколько дейтаграмм, и данные, переданные последовательными вызовами sendto
, никогда не объединяются в одну дейтаграмму.
Функцию sendto
можно использовать с сокетами, не привязанными к адресу. В этом случае внутри библиотеки сокетов будет неявно вызвана функция bind
для привязки сокета к адресу INADDR_ANY
и нулевому порту (т.е. адрес и порт будут выбраны системой).
Если выходной буфер сокета имеет ненулевой размер, sendto
помещает данные в этот буфер и сразу возвращает управление программе, а собственно отправка данных осуществляется библиотекой сокетов в фоновом режиме. Поэтому успешное завершение sendto
гарантирует только то, что данные скопированы в буфер и что на момент их копирования не обнаружено никаких проблем, которые делали бы невозможной их отправку. Но такие проблемы могут возникнуть позже, поэтому даже в случае успешного завершения sendto
отправитель не получает гарантии, что данные посланы. Если в выходном буфере сокета не хватает места для новой порции данных, sendto
не возвращает управление программе (т.е. блокирует ее) до тех пор, пока в буфере за счет фоновой отправки не появится достаточно места или не будет обнаружена ошибка.
Если размер выходного буфера сокета равен нулю, функция sendto
копирует данные сразу в сеть, без промежуточной буферизации. Когда функция вернет управление программе, программа может быть уверена, что информация уже успешно передана в сеть. Однако даже в этом случае успешное завершение sendto
не гарантирует доставку информации: дейтаграмма может потеряться по дороге.
В случае успешного завершения функция sendto
возвращает количество байтов, скопированных в буфер (или переданных напрямую в сеть, если буфера нет). Для протокола UDP это значение может быть равно только значению параметра len
, хотя для некоторых других протоколов (например, TCP) возможны ситуации, когда в буфер сокета копируется только часть данных, переданных программой, и тогда sendto
возвращает значение в диапазоне от 1 до len
. Если при выполнении sendto
возникает ошибка, она возвращает значение SOCKET_ERROR
(эта константа имеет отрицательное значение).
Для получения данных, присланных сокету, предназначена функция recvfrom
, имеющая следующий прототип:
function recvfrom(s: TSocket; var Buf; len, flags: Integer; var from: TSockAddr; var fromlen: Integer): Integer;
Параметр s
задает сокет, из входного буфера которого будут извлекаться данные, Buf
— буфер, в который эти данные будут копироваться, а len — размер этого буфера. Параметр flags
задает дополнительные опции и в большинстве случаев должен быть равен нулю. Параметр from
выходной: в него помещается адрес, с которого была послана дейтаграмма. Параметр fromlen
задает размер в байтах буфера для адреса отправителя. При вызове функции значение переменной, подставляемой в качестве фактического параметра, должно быть равно SizeOf(TSockAddr)
. Функция меняет это значение на ту длину, которая реально потребовалась для хранения адреса отправителя (в случае UDP это значение также будет равно SizeOf(TSockAddr)
.
В оригинале параметры from
и fromlen
передаются как указатели, и программа может использовать вместо них нулевые указатели, если ее не интересует адрес отправителя. Разработчики модуля WinSock
заменили указатели параметрами-переменными, что в большинстве случаев удобнее. Но для передачи нулевых указателей приходится в качестве фактических параметров подставлять неуклюжие конструкции PSockAddr(nil)^
и PInteger(nil)^
.