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 检索特定的错误代码。

错误代码 含义
WSANOTINITIALIZED
在使用此函数之前,必须成功调用 WSAStartup
WSAENETDOWN
网络子系统发生故障。
WSAEACCES
:请求的地址是广播地址,但相应的标志未设置。 使用 SO_BROADCAST 参数调用 setsockopt 以允许使用广播地址。
WSAEINVAL
指定了未知标志,或者为启用了SO_OOBINLINE的套接字指定了MSG_OOB。
WSAEINTR
阻止的 Windows 套接字 1.1 调用已通过 WSACancelBlockingCall 取消。
WSAEINPROGRESS
阻止 Windows 套接字 1.1 调用正在进行,或者服务提供商仍在处理回调函数。
WSAEFAULT
bufto 参数不是用户地址空间的一部分,或者被盗参数太小。
WSAENETRESET
由于操作执行过程中持续的活动检测到故障,连接损坏。
WSAENOBUFS
未提供任何缓冲区空间。
WSAENOTCONN
仅) (面向连接的套接字未连接套接字。
WSAENOTSOCK
:描述符不是套接字。
WSAEOPNOTSUPP
MSG_OOB指定,但套接字不是流样式(如类型SOCK_STREAM),与此套接字关联的通信域中不支持 OOB 数据,或者套接字是单向的,仅支持接收操作。
WSAESHUTDOWN
套接字已关闭;在调用关闭并设置为 SD_SEND 或 SD_BOTH 后,无法在套接字上 sendto。
WSAEWOULDBLOCK
:套接字标记为非阻止,请求的操作会进行阻止。
WSAEMSGSIZE
套接字面向消息,消息大于基础传输支持的最大值。
WSAEHOSTUNREACH
目前无法从此主机访问远程主机。
WSAECONNABORTED
由于超时或其他故障,虚拟线路已终止。 因为套接字不可再用,应用程序应关闭套接字。
WSAECONNRESET
执行硬性或异常关闭的远程端重置了虚拟线路。 对于 UDP 套接字,远程主机无法传递以前发送的 UDP 数据报,并使用“端口无法访问”ICMP 数据包进行响应。 因为套接字不可再用,应用程序应关闭套接字。
WSAEADDRNOTAVAIL
远程地址不是有效的地址,例如,ADDR_ANY。
WSAEAFNOSUPPORT
指定系列中的地址无法与此套接字一起使用。
WSAEDESTADDRREQ
:需要目标地址。
WSAENETUNREACH
此时不可以从此主机访问该网络。
WSAEHOSTUNREACH
套接字操作尝试访问无法访问的主机。
WSAETIMEDOUT
由于网络故障或另一端的系统在未通知的情况下关闭,连接已断开。

备注

sendto 函数用于在套接字上写入传出数据。 对于面向消息的套接字,必须注意不要超过基础子网的最大数据包大小,这可以通过使用 getsockopt 检索套接字选项的值SO_MAX_MSG_SIZE获得。 如果数据太长,无法通过基础协议以原子方式传递,则会返回错误 WSAEMSGSIZE ,并且不会传输任何数据。

to 参数可以是套接字地址系列中的任何有效地址,包括广播地址或任何多播地址。 若要发送到广播地址,应用程序必须使用 启用了SO_BROADCAST的 setsockopt 。 否则, sendto 将失败并显示错误代码 WSAEACCES。 对于 TCP/IP,应用程序可以发送到任何多播地址 (,而无需成为组成员) 。

注意 如果打开套接字,进行 setsockopt 调用,然后进行 sendto 调用,Windows 套接字将执行隐式 绑定 函数调用。
 
如果套接字未绑定,系统会将唯一值分配给本地关联,然后将套接字标记为绑定。 如果套接字已连接,则 getsockname 函数可用于确定与套接字关联的本地 IP 地址和端口。

如果未连接套接字,则为
getockname 函数可用于确定与套接字关联的本地端口号,但返回的 IP 地址设置为给定协议的通配符地址 (例如,INADDR_ANY或 IPv4 的“0.0.0.0”,对于 IPv6) IN6ADDR_ANY_INIT或“::”。

sendto 的成功完成并不表示数据已成功传递。

sendto 函数通常用于无连接套接字,以将数据报发送到由 to 参数标识的特定对等套接字。 即使无连接套接字以前已连接到特定地址, to 参数也仅覆盖该特定数据报的目标地址。 在面向连接的套接字上,忽略 totolen 参数,使 sendto 等效于 send

注意 发出阻止的 Winsock 调用(如 sendto)时,Winsock 可能需要等待网络事件,然后才能完成呼叫。 在这种情况下,Winsock 执行可发出警报的等待, (在同一线程上计划的 APC) 异步过程调用可能会中断。 在 APC 内发出另一个阻止 Winsock 调用,该调用中断了同一线程上正在进行的阻止 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发送广播 (,可以构造 由 参数 指向的地址,以包含 Winsock2.h) 中定义的特殊 IPv4 地址INADDR_BROADCAST (以及预期的端口号。 如果 由 to 参数指向的地址包含INADDR_BROADCAST地址和预期端口,则广播将在所有接口上发送到该端口。

如果广播只应在特定接口上发送,则 to 参数指向的地址应包含接口的子网广播地址和预期端口。 例如,子网掩码为 255.255.255.0 的 IPv4 网络地址 192.168.1.0 将使用子网广播地址 192.168.1.255。

广播数据报通常不应超过出现的碎片的大小,这意味着数据报的数据部分(不包括标头)不应超过 512 字节。

如果传输系统中没有可用于保存要传输的数据的缓冲区空间,除非套接字已置于非阻止模式, 否则 sendto 将阻止。 在非阻止、面向流的套接字上,写入的字节数可以介于 1 和请求的长度之间,具体取决于客户端和服务器系统上的缓冲区可用性。 selectWSAAsyncSelectWSAEventSelect 函数可用于确定何时可以发送更多数据。

允许使用 len 为零调用 sendto,并将返回零作为有效值。 对于面向消息的套接字,将发送零长度传输数据报。

flags 参数可用于影响为关联套接字指定的选项之外的函数调用行为。 此函数的语义由套接字选项和 flags 参数确定。 后者是使用以下任一值的按位 OR 运算符构造的。

含义
MSG_DONTROUTE :指定数据不应受到路由的约束。 Windows 套接字服务提供程序可以选择忽略此标志。
MSG_OOB 仅) (流式套接字(例如SOCK_STREAM)发送 OOB 数据。
 

Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。

Windows 8.1Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。

要求

   
最低受支持的客户端 Windows 8.1、Windows Vista [桌面应用 |UWP 应用]
最低受支持的服务器 Windows Server 2003 [桌面应用 | UWP 应用]
目标平台 Windows
标头 winsock.h (包括 Winsock2.h)
Library Ws2_32.lib
DLL Ws2_32.dll

另请参阅

WSAAsyncSelect

WSAEventSelect

Winsock 函数

Winsock 参考

recv

recvfrom

select

send

socket