Поделиться через


Функция sendto (winsock.h)

Функция sendto отправляет данные в определенное место назначения.

Синтаксис

int sendto(
  [in] SOCKET         s,
  [in] const char     *buf,
  [in] int            len,
  [in] int            flags,
  [in] const sockaddr *to,
  [in] int            tolen
);

Параметры

[in] s

Дескриптор, определяющий сокет (возможно, подключенный).

[in] buf

Указатель на буфер, содержащий передаваемые данные.

[in] len

Длина (в байтах) данных, на которые указывает параметр buf .

[in] flags

Набор флагов, указывающих способ вызова.

[in] to

Необязательный указатель на структуру sockaddr , содержащую адрес целевого сокета.

[in] tolen

Размер (в байтах) адреса, на который указывает параметр to .

Возвращаемое значение

Если ошибка не возникает, функция sendto возвращает общее количество отправленных байтов, которое может быть меньше числа, указанного в len. В противном случае возвращается значение SOCKET_ERROR, а определенный код ошибки можно получить, вызвав WSAGetLastError.

Код ошибки Значение
WSANOTINITIALISED
Перед использованием этой функции должен произойти успешный вызов WSAStartup .
WSAENETDOWN
Произошел сбой сетевой подсистемы.
WSAEACCES
Запрошенный адрес является широковещательным, но соответствующий флаг не установлен. Вызовите метод setsockopt с параметром SO_BROADCAST, чтобы разрешить использование широковещательного адреса.
WSAEINVAL
Был указан неизвестный флаг или MSG_OOB для сокета с включенным SO_OOBINLINE.
WSAEINTR
Блокирующий вызов Windows Sockets 1.1 был отменен через WSACancelBlockingCall.
WSAEINPROGRESS
Выполняется блокирующий вызов Windows Sockets 1.1 или поставщик услуг по-прежнему обрабатывает функцию обратного вызова.
WSAEFAULT
Параметры buf или to не являются частью адресного пространства пользователя или параметр tolen слишком мал.
WSAENETRESET
Подключение было разорвано из-за действия поддержания активности, обнаруживающего сбой во время выполнения операции.
WSAENOBUFS
Нет свободного места в буфере.
WSAENOTCONN
Сокет не подключен (только сокеты, ориентированные на подключение).
WSAENOTSOCK
Дескриптор не является сокетом.
WSAEOPNOTSUPP
MSG_OOB указано, но сокет не является потоковым, например тип SOCK_STREAM, данные OOB не поддерживаются в домене связи, связанном с этим сокетом, или сокет является однонаправленным и поддерживает только операции получения.
WSAESHUTDOWN
Сокет был выключен; невозможно отправить в сокет после вызова завершения работыс параметром SD_SEND или SD_BOTH.
WSAEWOULDBLOCK
Сокет помечается как неблокировочный, и запрошенная операция будет блокироваться.
WSAEMSGSIZE
Сокет ориентирован на сообщения, и сообщение больше максимального значения, поддерживаемого базовым транспортом.
WSAEHOSTUNREACH
В настоящее время с этого узла не удается связаться с удаленным узлом.
WSAECONNABORTED
Виртуальное подключение разорвано из-за тайм-аута или иного сбоя. Приложение должно закрыть сокет, поскольку он больше не может использоваться.
WSAECONNRESET
Виртуальное подключение было сброшено удаленной стороной путем прерывания. Для сокетов UDP удаленный узел не смог доставить ранее отправленную датаграмму UDP и ответил пакетом ICMP "Порт недоступен". Приложение должно закрыть сокет, поскольку он больше не может использоваться.
WSAEADDRNOTAVAIL
Удаленный адрес не является допустимым адресом, например ADDR_ANY.
WSAEAFNOSUPPORT
Адреса из заданного семейства адресов не могут использоваться с этим сокетом.
WSAEDESTADDRREQ
Требуется адрес назначения.
WSAENETUNREACH
В настоящее время сеть недоступна с этого узла.
WSAEHOSTUNREACH
Сделана попытка выполнить операцию на сокете для недоступного хоста.
WSAETIMEDOUT
Подключение было прервано из-за сбоя сети или из-за того, что система на другом конце не работает без предварительного уведомления.

Комментарии

Функция sendto используется для записи исходящих данных в сокет. Для сокетов, ориентированных на сообщения, необходимо соблюдать осторожность, чтобы не превышать максимальный размер пакета базовых подсетей, который можно получить с помощью команды getsockopt для получения значения параметра сокета SO_MAX_MSG_SIZE. Если данные слишком длинны для атомарной передачи через базовый протокол, возвращается ошибка WSAEMSGSIZE и данные не передаются.

Параметр to может быть любым допустимым адресом в семействе адресов сокета, включая широковещательный или любой адрес многоадресной рассылки. Для отправки на широковещательный адрес приложение должно использовать setsockopt с включенным SO_BROADCAST. В противном случае sendto завершится ошибкой с кодом WSAEACCES. Для TCP/IP приложение может отправлять сообщения на любой адрес многоадресной рассылки (не становясь участником группы).

Примечание Если открывается сокет, выполняется вызов setsockopt , а затем выполняется вызов sendto , Windows Sockets выполняет неявный вызов функции привязки .
 
Если сокет не привязан, система присваивает ему уникальные значения, а затем помечается как привязанный. Если сокет подключен, функцию getsockname можно использовать для определения локального IP-адреса и порта, связанных с сокетом.

Если сокет не подключен,
Функцию getockname можно использовать для определения номера локального порта, связанного с сокетом, но возвращаемый IP-адрес устанавливается в качестве подстановочного адреса для заданного протокола (например, INADDR_ANY или "0.0.0.0" для IPv4 и IN6ADDR_ANY_INIT или "::" для IPv6).

Успешное завершение отправки не означает, что данные были успешно доставлены.

Функция sendto обычно используется в сокете без подключения для отправки датаграммы в конкретный одноранговый сокет, определенный параметром to . Даже если сокет без подключения был ранее подключен к определенному адресу, параметр to переопределяет адрес назначения только для этой датаграммы. В сокете, ориентированном на подключение, параметры to и tolen игнорируются, что делает sendto эквивалентным отправке.

Примечание При выполнении блокирующего вызова Winsock, например sendto, Winsock может потребоваться дождаться сетевого события, прежде чем вызов сможет завершиться. В этой ситуации Winsock выполняет оповещенное ожидание, которое может быть прервано асинхронным вызовом процедуры (APC), запланированным в том же потоке. Выполнение другого блокирующего вызова Winsock внутри APC, который прервал текущий блокирующий вызов Winsock в том же потоке, приведет к неопределенному поведению, и клиенты Winsock никогда не должны пытаться его выполнять.
 

Пример кода

В следующем примере показано использование функции sendto .
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

int main()
{

    int iResult;
    WSADATA wsaData;

    SOCKET SendSocket = INVALID_SOCKET;
    sockaddr_in RecvAddr;

    unsigned short Port = 27015;

    char SendBuf[1024];
    int BufLen = 1024;

    //----------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    //---------------------------------------------
    // Create a socket for sending data
    SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (SendSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //---------------------------------------------
    // Set up the RecvAddr structure with the IP address of
    // the receiver (in this example case "192.168.1.1")
    // and the specified port number.
    RecvAddr.sin_family = AF_INET;
    RecvAddr.sin_port = htons(Port);
    RecvAddr.sin_addr.s_addr = inet_addr("192.168.1.1");

    //---------------------------------------------
    // Send a datagram to the receiver
    wprintf(L"Sending a datagram to the receiver...\n");
    iResult = sendto(SendSocket,
                     SendBuf, BufLen, 0, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
    if (iResult == SOCKET_ERROR) {
        wprintf(L"sendto failed with error: %d\n", WSAGetLastError());
        closesocket(SendSocket);
        WSACleanup();
        return 1;
    }
    //---------------------------------------------
    // When the application is finished sending, close the socket.
    wprintf(L"Finished sending. Closing socket.\n");
    iResult = closesocket(SendSocket);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"closesocket failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //---------------------------------------------
    // Clean up and quit.
    wprintf(L"Exiting.\n");
    WSACleanup();
    return 0;
}


Для сокетов, использующих IP-адрес (версия 4)

Для отправки широковещательной рассылки (только на SOCK_DGRAM) можно создать адрес, на который указывает параметр to , содержащий специальный IPv4-адрес INADDR_BROADCAST (определенный в Winsock2.h) вместе с предполагаемым номером порта. Если адрес, на который указывает параметр to , содержит адрес INADDR_BROADCAST и предполагаемый порт, трансляция будет отправляться на этот порт по всем интерфейсам.

Если широковещательная рассылка должна быть отправлена только через определенный интерфейс, то адрес, на который указывает параметр to , должен содержать адрес широковещательной подсети для интерфейса и предполагаемый порт. Например, сетевой адрес IPv4 192.168.1.0 с маской подсети 255.255.255.0 будет использовать широковещательный адрес подсети 192.168.1.255.

Как правило, не рекомендуется, чтобы широковещательная датаграмма превышала размер, при котором может произойти фрагментация, что означает, что часть данных датаграммы (за исключением заголовков) не должна превышать 512 байт.

Если в транспортной системе нет буферного пространства для хранения передаваемых данных, sendto будет блокироваться, если сокет не был помещен в неблокировочный режим. При неблокировке потоковых сокетов число записанных байтов может составлять от 1 до требуемой длины в зависимости от доступности буфера в клиентской и серверной системах. Функция select, WSAAsyncSelect или WSAEventSelect может использоваться для определения возможности отправки дополнительных данных.

Вызов sendto с len 0 является допустимым и возвращает ноль в качестве допустимого значения. Для сокетов, ориентированных на сообщения, отправляется транспортная датаграмма нулевой длины.

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

Значение Значение
MSG_DONTROUTE Указывает, что данные не должны подвергаться маршрутизации. Поставщик службы Сокетов Windows может игнорировать этот флаг.
MSG_OOB Отправляет данные OOB (только сокет в стиле потока, например SOCK_STREAM).
 

Windows Phone 8. Эта функция поддерживается для приложений Магазина Windows Phone Windows Phone 8 и более поздних версий.

Windows 8.1 и Windows Server 2012 R2: эта функция поддерживается для приложений Магазина Windows на Windows 8.1, Windows Server 2012 R2 и более поздних версий.

Требования

   
Минимальная версия клиента Windows 8.1, Windows Vista [классические приложения | Приложения UWP]
Минимальная версия сервера Windows Server 2003 [классические приложения | Приложения UWP]
Целевая платформа Windows
Header winsock.h (включая Winsock2.h)
Библиотека Ws2_32.lib
DLL Ws2_32.dll

См. также раздел

WSAsyncSelect

WSAEventSelect

Функции Winsock

Справочник по Winsock

Recv

recvfrom

select

send

Сокета