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
要求的位址是廣播位址,但未設定適當的旗標。 使用 SO_BROADCAST 參數呼叫 setsockopt ,以允許使用廣播位址。
WSAEINVAL
已指定未知旗標,或為啟用SO_OOBINLINE的通訊端指定MSG_OOB。
WSAEINTR
封鎖的 Windows Sockets 1.1 呼叫已透過 WSACancelBlockingCall取消。
WSAEINPROGRESS
封鎖的 Windows Sockets 1.1 呼叫正在進行中,或服務提供者仍在處理回呼函式。
WSAEFAULT
bufto參數不是使用者位址空間的一部分,或遭竊的參數太小。
WSAENETRESET
連線已中斷,因為持續運作活動偵測作業正在進行時失敗。
WSAENOBUFS
沒有可用的緩衝區空間。
WSAENOTCONN
通訊端未 (連線導向通訊端) 。
WSAENOTSOCK
描述項不是通訊端。
WSAEOPNOTSUPP
已指定MSG_OOB,但通訊端不是資料流程樣式,例如類型SOCK_STREAM、與此通訊端相關聯的通訊網域不支援 OOB 資料,或通訊端是單向的,而且僅支援接收作業。
WSAESHUTDOWN
通訊端已關閉;在 叫用關機 之後,無法傳送至通訊端上的 sendto ,其方式設定 為 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參數可以是通訊端位址系列中的任何有效位址,包括廣播或任何多播位址。 若要傳送至廣播位址,應用程式必須使用 setockopt 並啟用SO_BROADCAST。 否則, sendto 將會失敗,並出現錯誤碼 WSAEACCES。 針對 TCP/IP,應用程式可以傳送至任何多播位址 (,而不需要成為群組成員) 。

注意 如果開啟通訊端,就會進行 setockopt 呼叫,然後進行 sendto 呼叫,Windows Sockets 會執行隱含 系結 函式呼叫。
 
如果通訊端未系結,系統會將唯一值指派給本機關聯,然後通訊端會標示為系結。 如果通訊端已連線, 則會使用 getsockname 函式來判斷與通訊端相關聯的本機 IP 位址和埠。

如果通訊端未連接,則 為
getsockname 函式可用來判斷與通訊端相關聯的本機埠號碼,但傳回的 IP 位址會設定為指定通訊協定的萬用字元位址 (例如,INADDR_ANY或 「0.0.0.0」 用於 IPv4,IN6ADDR_ANY_INIT或 「::」 表示 IPv6) 。

成功完成 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上傳送廣播 (,可以建構 to 參數所指向的位址,以包含 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 Sockets 服務提供者可以選擇忽略此旗標。
MSG_OOB (資料流程樣式通訊端傳送 OOB 資料,例如只SOCK_STREAM) 。
 

Windows Phone 8:Windows Phone 8 和更新版本Windows Phone市集應用程式支援此函式。

Windows 8.1Windows Server 2012 R2:Windows 市集應用程式支援此功能,Windows 8.1、Windows Server 2012 R2 及更新版本。

規格需求

   
最低支援的用戶端 Windows 8.1、Windows Vista [傳統型應用程式 |UWP 應用程式]
最低支援的伺服器 Windows Server 2003 [傳統型應用程式 |UWP 應用程式]
目標平台 Windows
標頭 winsock.h (包含 Winsock2.h)
程式庫 Ws2_32.lib
Dll Ws2_32.dll

另請參閱

WSAAsyncSelect

WSAEventSelect

Winsock 函式

Winsock 參考

recv

recvfrom

select

send

socket