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 检索特定的错误代码。
错误代码 | 含义 |
---|---|
在使用此函数之前,必须成功调用 WSAStartup 。 | |
网络子系统发生故障。 | |
:请求的地址是广播地址,但相应的标志未设置。 使用 SO_BROADCAST 参数调用 setsockopt 以允许使用广播地址。 | |
指定了未知标志,或者为启用了SO_OOBINLINE的套接字指定了MSG_OOB。 | |
阻止的 Windows 套接字 1.1 调用已通过 WSACancelBlockingCall 取消。 | |
阻止 Windows 套接字 1.1 调用正在进行,或者服务提供商仍在处理回调函数。 | |
buf 或 to 参数不是用户地址空间的一部分,或者被盗参数太小。 | |
由于操作执行过程中持续的活动检测到故障,连接损坏。 | |
未提供任何缓冲区空间。 | |
仅) (面向连接的套接字未连接套接字。 | |
:描述符不是套接字。 | |
MSG_OOB指定,但套接字不是流样式(如类型SOCK_STREAM),与此套接字关联的通信域中不支持 OOB 数据,或者套接字是单向的,仅支持接收操作。 | |
套接字已关闭;在调用关闭并设置为 SD_SEND 或 SD_BOTH 后,无法在套接字上 sendto。 | |
:套接字标记为非阻止,请求的操作会进行阻止。 | |
套接字面向消息,消息大于基础传输支持的最大值。 | |
目前无法从此主机访问远程主机。 | |
由于超时或其他故障,虚拟线路已终止。 因为套接字不可再用,应用程序应关闭套接字。 | |
执行硬性或异常关闭的远程端重置了虚拟线路。 对于 UDP 套接字,远程主机无法传递以前发送的 UDP 数据报,并使用“端口无法访问”ICMP 数据包进行响应。 因为套接字不可再用,应用程序应关闭套接字。 | |
远程地址不是有效的地址,例如,ADDR_ANY。 | |
指定系列中的地址无法与此套接字一起使用。 | |
:需要目标地址。 | |
此时不可以从此主机访问该网络。 | |
套接字操作尝试访问无法访问的主机。 | |
由于网络故障或另一端的系统在未通知的情况下关闭,连接已断开。 |
备注
sendto 函数用于在套接字上写入传出数据。 对于面向消息的套接字,必须注意不要超过基础子网的最大数据包大小,这可以通过使用 getsockopt 检索套接字选项的值SO_MAX_MSG_SIZE获得。 如果数据太长,无法通过基础协议以原子方式传递,则会返回错误 WSAEMSGSIZE ,并且不会传输任何数据。
to 参数可以是套接字地址系列中的任何有效地址,包括广播地址或任何多播地址。 若要发送到广播地址,应用程序必须使用 启用了SO_BROADCAST的 setsockopt 。 否则, sendto 将失败并显示错误代码 WSAEACCES。 对于 TCP/IP,应用程序可以发送到任何多播地址 (,而无需成为组成员) 。
如果未连接套接字,则为
getockname 函数可用于确定与套接字关联的本地端口号,但返回的 IP 地址设置为给定协议的通配符地址 (例如,INADDR_ANY或 IPv4 的“0.0.0.0”,对于 IPv6) IN6ADDR_ANY_INIT或“::”。
sendto 的成功完成并不表示数据已成功传递。
sendto 函数通常用于无连接套接字,以将数据报发送到由 to 参数标识的特定对等套接字。 即使无连接套接字以前已连接到特定地址, to 参数也仅覆盖该特定数据报的目标地址。 在面向连接的套接字上,忽略 to 和 tolen 参数,使 sendto 等效于 send。
示例代码
以下示例演示如何使用 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 和请求的长度之间,具体取决于客户端和服务器系统上的缓冲区可用性。 select、WSAAsyncSelect 或 WSAEventSelect 函数可用于确定何时可以发送更多数据。
允许使用 len 为零调用 sendto,并将返回零作为有效值。 对于面向消息的套接字,将发送零长度传输数据报。
flags 参数可用于影响为关联套接字指定的选项之外的函数调用行为。 此函数的语义由套接字选项和 flags 参数确定。 后者是使用以下任一值的按位 OR 运算符构造的。
值 | 含义 |
---|---|
MSG_DONTROUTE | :指定数据不应受到路由的约束。 Windows 套接字服务提供程序可以选择忽略此标志。 |
MSG_OOB | 仅) (流式套接字(例如SOCK_STREAM)发送 OOB 数据。 |
Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。
Windows 8.1和 Windows 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 |