WSASendTo-Funktion (winsock2.h)
Die WSASendTo-Funktion sendet Daten an ein bestimmtes Ziel, wobei ggf. überlappende E/A-Vorgänge verwendet werden.
Syntax
int WSAAPI WSASendTo(
[in] SOCKET s,
[in] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesSent,
[in] DWORD dwFlags,
[in] const sockaddr *lpTo,
[in] int iTolen,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
Parameter
[in] s
Ein Deskriptor, der einen (möglicherweise verbundenen) Socket identifiziert.
[in] lpBuffers
Ein Zeiger auf ein Array von WSABUF-Strukturen . Jede WSABUF-Struktur enthält einen Zeiger auf einen Puffer und die Länge des Puffers in Bytes. Bei einer Winsock-Anwendung besitzt das System nach dem Aufruf der WSASendTo-Funktion diese Puffer, und die Anwendung greift möglicherweise nicht darauf zu. Dieses Array muss für die Dauer des Sendevorgangs gültig bleiben.
[in] dwBufferCount
Die Anzahl der WSABUF-Strukturen im lpBuffers-Array .
[out] lpNumberOfBytesSent
Ein Zeiger auf die Anzahl der von diesem Aufruf gesendeten Bytes, wenn der E/A-Vorgang sofort abgeschlossen wird.
Verwenden Sie NULL für diesen Parameter, wenn der lpOverlapped-Parameter nicht NULL ist, um potenziell fehlerhafte Ergebnisse zu vermeiden. Dieser Parameter kann nur NULL sein, wenn der lpOverlapped-Parameter nicht NULL ist.
[in] dwFlags
Die Flags, die zum Ändern des Verhaltens des WSASendTo-Funktionsaufrufs verwendet werden.
[in] lpTo
Ein optionaler Zeiger auf die Adresse des Zielsockets in der SOCKADDR-Struktur .
[in] iTolen
Die Größe der Adresse im lpTo-Parameter in Bytes.
[in] lpOverlapped
Ein Zeiger auf eine WSAOVERLAPPED-Struktur (bei nicht überlappten Sockets ignoriert).
[in] lpCompletionRoutine
Typ: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
Ein Zeiger auf die Vervollständigungsroutine, die aufgerufen wird, wenn der Sendevorgang abgeschlossen wurde (bei nicht überlappten Sockets ignoriert).
Rückgabewert
Wenn kein Fehler auftritt und der Sendevorgang sofort abgeschlossen wurde, gibt WSASendTo null zurück. In diesem Fall wurde der Aufruf der Vervollständigungsroutine bereits geplant, sobald sich der aufrufende Thread im warnbaren Zustand befindet. Andernfalls wird der Wert SOCKET_ERROR zurückgegeben, und ein bestimmter Fehlercode kann durch Aufrufen von WSAGetLastError abgerufen werden. Der Fehlercode WSA_IO_PENDING gibt an, dass der überlappende Vorgang erfolgreich initiiert wurde und dass die Vervollständigung zu einem späteren Zeitpunkt angezeigt wird. Jeder andere Fehlercode gibt an, dass der überlappende Vorgang nicht erfolgreich initiiert wurde und keine Vervollständigungsanzeige auftritt.
Fehlercode | Bedeutung |
---|---|
Die angeforderte Adresse ist eine Broadcastadresse, aber das entsprechende Flag wurde nicht festgelegt. | |
Die Remoteadresse ist keine gültige Adresse (z. B. ADDR_ANY). | |
Adressen in der angegebenen Adressfamilie können nicht mit diesem Socket verwendet werden. | |
Bei einem UDP-Datagrammsocket würde dieser Fehler darauf hindeuten, dass ein vorheriger Sendevorgang zu einer ICMP-Meldung "Port Unreachable" geführt hat. | |
Eine Zieladresse ist erforderlich. | |
Die Parameter lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent oder lpCompletionRoutine sind nicht Teil des Benutzeradressraums, oder der lpTo-Parameter ist zu klein. | |
Versuch eines Socketvorgangs für einen nicht erreichbaren Host. | |
Ein blockierter Windows Sockets 1.1-Aufruf wird ausgeführt, oder der Dienstanbieter verarbeitet weiterhin eine Rückruffunktion. | |
Ein blockierender Windows Socket 1.1-Aufruf wurde über WSACancelBlockingCall abgebrochen. | |
Der Socket wurde nicht an bind gebunden, oder der Socket wird nicht mit dem überlappenden Flag erstellt. | |
Der Socket ist nachrichtenorientiert, und die Nachricht ist größer als das maximum, das vom zugrunde liegenden Transport unterstützt wird. | |
Beim Netzwerksubsystem ist ein Fehler aufgetreten. | |
Für einen Datagrammsocket zeigt dieser Fehler an, dass die Gültigkeitsdauer abgelaufen ist. | |
Das Netzwerk kann von diesem Host zurzeit nicht erreicht werden. | |
Der Windows Sockets-Anbieter meldet einen Puffer-Deadlock. | |
Der Socket ist nicht verbunden (nur verbindungsorientierte Sockets). | |
Der Deskriptor ist kein Socket. | |
Der Socket wurde heruntergefahren. Es ist nicht möglich, WSASendTo auf einem Socket zu verwenden, nachdem das Herunterfahren aufgerufen wurde und wie auf SD_SEND oder SD_BOTH festgelegt ist. | |
Windows NT:
Überlappende Sockets: Es gibt zu viele ausstehende überlappende E/A-Anforderungen. Nicht überlappte Sockets: Der Socket ist als nicht blockiert gekennzeichnet, und der Sendevorgang kann nicht sofort abgeschlossen werden. |
|
Vor der Verwendung dieser Funktion muss ein erfolgreicher WSAStartup-Aufruf erfolgen. | |
Ein überlappender Vorgang wurde erfolgreich eingeleitet, und der Abschluss wird zu einem späteren Zeitpunkt angezeigt. | |
Der überlappende Vorgang wurde aufgrund des Schließens des Sockets oder der Ausführung des befehls SIO_FLUSH in WSAIoctl abgebrochen. |
Hinweise
Die WSASendTo-Funktion bietet erweiterte Funktionen gegenüber der Standardmäßigen sendto-Funktion in zwei wichtigen Bereichen:
- Es kann in Verbindung mit überlappenden Sockets verwendet werden, um überlappende Sendevorgänge auszuführen.
- Dadurch können mehrere Sendepuffer angegeben werden, sodass sie auf den Scatter/Gather-Typ von E/A anwendbar sind.
Für überlappende Sockets (erstellt mit WSASocket mit Flag WSA_FLAG_OVERLAPPED) verwendet das Senden von Daten überlappende E/A, es sei denn, sowohl lpOverlapped als auch lpCompletionRoutine sind NULL . In diesem Fall wird der Socket als nicht überlappter Socket behandelt. Eine Vervollständigungsanzeige (aufruft die Vervollständigungsroutine oder Einstellung eines Ereignisobjekts), wenn die Puffer vom Transport verbraucht wurden. Wenn der Vorgang nicht sofort abgeschlossen wird, wird der endgültige Abschluss status über die Vervollständigungsroutine oder WSAGetOverlappedResult abgerufen.
Bei nicht überlappten Sockets werden die letzten beiden Parameter (lpOverlapped, lpCompletionRoutine) ignoriert, und WSASendTo verwendet die gleiche blockierende Semantik wie send. Daten werden aus den Puffern in den Transportpuffer kopiert. Wenn der Socket nicht blockierend und streamorientiert ist und nicht genügend Speicherplatz im Puffer des Transports vorhanden ist, gibt WSASendTo zurück, wobei nur ein Teil der Puffer der Anwendung verbraucht wurde. Bei derselben Puffersituation und einem blockierenden Socket wird WSASendTo blockiert, bis der gesamte Pufferinhalt der Anwendung genutzt wurde.
Wenn diese Funktion überlappend ausgeführt wird, liegt es in der Verantwortung des Winsock-Dienstanbieters, die WSABUF-Strukturen zu erfassen, bevor sie von diesem Aufruf zurückgegeben werden. Dadurch können Anwendungen stapelbasierte WSABUF-Arrays erstellen, auf die der lpBuffers-Parameter verweist.
Bei nachrichtenorientierten Sockets muss darauf geachtet werden, dass die maximale Nachrichtengröße des zugrunde liegenden Transports nicht überschritten wird, die durch Abrufen des Werts der Socketoption SO_MAX_MSG_SIZE abgerufen werden kann. Wenn die Daten zu lang sind, um das zugrunde liegende Protokoll atomar zu durchlaufen, wird der Fehler WSAEMSGSIZE zurückgegeben, und es werden keine Daten übertragen.
Wenn der Socket ungebunden ist, werden der lokalen Zuordnung vom System eindeutige Werte zugewiesen, und der Socket wird dann als gebunden markiert.
Wenn der Socket verbunden ist, kann die funktion getsockname verwendet werden, um die lokale IP-Adresse und den port zu bestimmen, die dem Socket zugeordnet sind.
Wenn der Socket nicht verbunden ist, ist die
die getockname-Funktion kann verwendet werden, um die dem Socket zugeordnete lokale Portnummer zu bestimmen, aber die zurückgegebene IP-Adresse wird auf die Platzhalteradresse für das angegebene Protokoll festgelegt (z. B. INADDR_ANY oder "0.0.0" für IPv4 und IN6ADDR_ANY_INIT oder "::" für IPv6).
Der erfolgreiche Abschluss eines WSASendTo bedeutet nicht, dass die Daten erfolgreich übermittelt wurden.
Der dwFlags-Parameter kann verwendet werden, um das Verhalten des Funktionsaufrufs über die für den zugeordneten Socket angegebenen Optionen hinaus zu beeinflussen. Das heißt, die Semantik dieser Funktion wird durch die Socketoptionen und den dwFlags-Parameter bestimmt. Letzteres wird mithilfe des bitweisen OR-Operators mit einem der in der folgenden Tabelle aufgeführten Werte erstellt.
Wert | Bedeutung |
---|---|
MSG_DONTROUTE | Gibt an, dass die Daten nicht routingpflichtig sein sollen. Ein Windows Socket-Dienstanbieter kann dieses Flag ignorieren. |
MSG_OOB | Senden sie OOB-Daten (nur SOCK_STREAM Socket im Streamformat). |
MSG_PARTIAL | Gibt an, dass lpBuffers nur eine partielle Nachricht enthält. Beachten Sie, dass der Fehlercode WSAEOPNOTSUPP von Transporten zurückgegeben wird, die partielle Nachrichtenübertragungen nicht unterstützen. |
Überlappende Socket-E/A
Wenn ein überlappender Vorgang sofort abgeschlossen wird, gibt WSASendTo den Wert 0 zurück, und der parameter lpNumberOfBytesSent wird mit der Anzahl der gesendeten Bytes aktualisiert. Wenn der überlappende Vorgang erfolgreich initiiert wurde und später abgeschlossen wird, gibt WSASendToSOCKET_ERROR zurück und gibt fehlercode WSA_IO_PENDING an. In diesem Fall wird lpNumberOfBytesSent nicht aktualisiert. Wenn der überlappende Vorgang abgeschlossen ist, wird die übertragene Datenmenge entweder über den cbTransferred-Parameter in der Vervollständigungsroutine (sofern angegeben) oder über den lpcbTransfer-Parameter in WSAGetOverlappedResult angegeben.Der lpOverlapped-Parameter muss für die Dauer des überlappenden Vorgangs gültig sein. Wenn mehrere E/A-Vorgänge gleichzeitig ausstehen, muss jeder auf eine separate WSAOVERLAPPED-Struktur verweisen.
Wenn der lpCompletionRoutine-ParameterNULL ist, wird der hEvent-Parameter von lpOverlapped signalisiert, wenn der überlappende Vorgang abgeschlossen wird, wenn er ein gültiges Ereignisobjekthandle enthält. Eine Anwendung kann WSAWaitForMultipleEvents oder WSAGetOverlappedResult verwenden, um das Ereignisobjekt zu warten oder abzufragen.
Wenn lpCompletionRoutine nicht NULL ist, wird der hEvent-Parameter ignoriert und kann von der Anwendung verwendet werden, um Kontextinformationen an die Vervollständigungsroutine zu übergeben. Ein Aufrufer, der eine nicht NULLlpCompletionRoutine übergibt und später WSAGetOverlappedResult für dieselbe überlappende E/A-Anforderung aufruft, legt den fWait-Parameter für diesen Aufruf von WSAGetOverlappedResult möglicherweise nicht auf TRUE fest. In diesem Fall ist die Verwendung des hEvent-Parameters nicht definiert, und der Versuch, auf den hEvent-Parameter zu warten, führt zu unvorhersehbaren Ergebnissen.
Die Vervollständigungsroutine folgt den gleichen Regeln wie für Windows-Datei-E/A-Vervollständigungsroutinen. Die Vervollständigungsroutine wird erst aufgerufen, wenn sich der Thread in einem warnbaren Wartezustand befindet, z. B. wenn die Funktion WSAWaitForMultipleEvents mit dem fAlertable-Parameter auf TRUE aufgerufen wird.
Transportanbieter ermöglichen einer Anwendung das Aufrufen von Sende- und Empfangsvorgängen aus dem Kontext der Socket-E/A-Vervollständigungsroutine und garantieren, dass E/A-Vervollständigungsroutinen für einen bestimmten Socket nicht geschachtelt werden. So können zeitsensible Datenübertragungen vollständig in einem präventiven Kontext erfolgen.
Der Prototyp der Vervollständigungsroutine sieht wie folgt aus.
void CALLBACK CompletionROUTINE(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
Die CompletionRoutine-Funktion ist ein Platzhalter für einen anwendungsdefinierten oder bibliotheksdefinierte Funktionsnamen. Der dwError-Parameter gibt die Vervollständigung status für den überlappenden Vorgang an, wie durch lpOverlapped angegeben. Der cbTransferred-Parameter gibt die Anzahl der gesendeten Bytes an. Derzeit sind keine Flagwerte definiert, und dwFlags ist 0. Diese Funktion gibt keinen Wert zurück.
Das Zurückgeben von dieser Funktion ermöglicht den Aufruf einer anderen ausstehenden Vervollständigungsroutine für diesen Socket. Alle wartenden Vervollständigungsroutinen werden aufgerufen, bevor die Wartezeit des warnungsfähigen Threads mit einem Rückgabecode von WSA_IO_COMPLETION erfüllt ist. Die Vervollständigungsroutinen können in beliebiger Reihenfolge aufgerufen werden, nicht unbedingt in derselben Reihenfolge, in der die überlappenden Vorgänge abgeschlossen werden. Es wird jedoch garantiert, dass die bereitgestellten Puffer in der angegebenen Reihenfolge gesendet werden.
Beispielcode
Im folgenden Beispiel wird die Verwendung der WSASendTo-Funktion mithilfe eines Ereignisobjekts veranschaulicht.#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")
int __cdecl main(int argc, char **argv)
{
//---------------------------------------------
// Declare and initialize variables
WSADATA wsaData;
WSABUF DataBuf;
WSAOVERLAPPED Overlapped;
SOCKET SendToSocket = INVALID_SOCKET;
struct sockaddr_in RecvAddr;
struct sockaddr_in LocalAddr;
int RecvAddrSize = sizeof (RecvAddr);
int LocalAddrSize = sizeof (LocalAddr);
u_short Port = 27777;
struct hostent *localHost;
char *ip;
char *targetip;
char *targetport;
char SendBuf[1024] = "Data buffer to send";
int BufLen = 1024;
DWORD BytesSent = 0;
DWORD Flags = 0;
int rc, err;
int retval = 0;
// Validate the parameters
if (argc != 3) {
printf("usage: %s targetip port\n", argv[0]);
printf(" to sendto the localhost on port 27777\n");
printf(" %s 127.0.0.1 27777\n", argv[0]);
return 1;
}
targetip = argv[1];
targetport = argv[2];
//---------------------------------------------
// Initialize Winsock
// Load Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (rc != 0) {
printf("Unable to load Winsock: %d\n", rc);
return 1;
}
// Make sure the Overlapped struct is zeroed out
SecureZeroMemory((PVOID) &Overlapped, sizeof(WSAOVERLAPPED));
// Create an event handle and setup the overlapped structure.
Overlapped.hEvent = WSACreateEvent();
if (Overlapped.hEvent == WSA_INVALID_EVENT) {
printf("WSACreateEvent failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
//---------------------------------------------
// Create a socket for sending data
SendToSocket =
WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0,
WSA_FLAG_OVERLAPPED);
if (SendToSocket == INVALID_SOCKET) {
printf("socket failed with error: %d\n", WSAGetLastError());
WSACloseEvent(Overlapped.hEvent);
WSACleanup();
return 1;
}
//---------------------------------------------
// Set up the RecvAddr structure with the IP address of
// the receiver (in this example case "123.123.123.1")
// and the specified port number.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_addr.s_addr = inet_addr(targetip);
if (RecvAddr.sin_addr.s_addr == INADDR_NONE) {
printf("The target ip address entered must be a legal IPv4 address\n");
WSACloseEvent(Overlapped.hEvent);
WSACleanup();
return 1;
}
RecvAddr.sin_port = htons( (u_short) atoi(targetport));
if(RecvAddr.sin_port == 0) {
printf("The targetport must be a legal UDP port number\n");
WSACloseEvent(Overlapped.hEvent);
WSACleanup();
return 1;
}
//---------------------------------------------
// Set up the LocalAddr structure with the local IP address
// and the specified port number.
localHost = gethostbyname("");
ip = inet_ntoa(*(struct in_addr *) *localHost->h_addr_list);
LocalAddr.sin_family = AF_INET;
LocalAddr.sin_addr.s_addr = inet_addr(ip);
LocalAddr.sin_port = htons(Port);
//---------------------------------------------
// Bind the sending socket to the LocalAddr structure
// that has the internet address family, local IP address
// and specified port number.
rc = bind(SendToSocket, (struct sockaddr *) &LocalAddr, LocalAddrSize);
if (rc == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
WSACloseEvent(Overlapped.hEvent);
closesocket(SendToSocket);
WSACleanup();
return 1;
}
//---------------------------------------------
// Send a datagram to the receiver
printf("Sending datagram from IPv4 address = %s port=%d\n",
inet_ntoa(LocalAddr.sin_addr), ntohs(LocalAddr.sin_port) );
printf(" to IPv4 address = %s port=%d\n",
inet_ntoa(RecvAddr.sin_addr), ntohs(RecvAddr.sin_port) );
// printf("Sending a datagram...\n");
DataBuf.len = BufLen;
DataBuf.buf = SendBuf;
rc = WSASendTo(SendToSocket, &DataBuf, 1,
&BytesSent, Flags, (SOCKADDR *) & RecvAddr,
RecvAddrSize, &Overlapped, NULL);
if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError()))) {
printf("WSASendTo failed with error: %d\n", err);
WSACloseEvent(Overlapped.hEvent);
closesocket(SendToSocket);
WSACleanup();
return 1;
}
rc = WSAWaitForMultipleEvents(1, &Overlapped.hEvent, TRUE, INFINITE, TRUE);
if (rc == WSA_WAIT_FAILED) {
printf("WSAWaitForMultipleEvents failed with error: %d\n",
WSAGetLastError());
retval = 1;
}
rc = WSAGetOverlappedResult(SendToSocket, &Overlapped, &BytesSent,
FALSE, &Flags);
if (rc == FALSE) {
printf("WSASendTo failed with error: %d\n", WSAGetLastError());
retval = 1;
}
else
printf("Number of sent bytes = %d\n", BytesSent);
//---------------------------------------------
// When the application is finished sending, close the socket.
printf("Finished sending. Closing socket.\n");
WSACloseEvent(Overlapped.hEvent);
closesocket(SendToSocket);
printf("Exiting.\n");
//---------------------------------------------
// Clean up and quit.
WSACleanup();
return (retval);
}
Windows Phone 8: Diese Funktion wird für Windows Phone Store-Apps auf Windows Phone 8 und höher unterstützt.
Windows 8.1 und Windows Server 2012 R2: Diese Funktion wird für Windows Store-Apps auf Windows 8.1, Windows Server 2012 R2 und höher unterstützt.
Anforderungen
Anforderung | Wert |
---|---|
Unterstützte Mindestversion (Client) | Windows 8.1, Windows Vista [Desktop-Apps | UWP-Apps] |
Unterstützte Mindestversion (Server) | Windows Server 2003 [Desktop-Apps | UWP-Apps] |
Zielplattform | Windows |
Kopfzeile | winsock2.h |
Bibliothek | Ws2_32.lib |
DLL | Ws2_32.dll |