WSARecvFrom-Funktion (winsock2.h)
Die WSARecvFrom-Funktion empfängt ein Datagramm und speichert die Quelladresse.
Syntax
int WSAAPI WSARecvFrom(
[in] SOCKET s,
[in, out] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesRecvd,
[in, out] LPDWORD lpFlags,
[out] sockaddr *lpFrom,
[in, out] LPINT lpFromlen,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
Parameter
[in] s
Ein Deskriptor, der einen Socket identifiziert.
[in, out] 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] dwBufferCount
Die Anzahl der WSABUF-Strukturen im lpBuffers-Array .
[out] lpNumberOfBytesRecvd
Ein Zeiger auf die Anzahl der Bytes, die von diesem Aufruf empfangen werden, wenn der WSARecvFrom-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, out] lpFlags
Ein Zeiger auf Flags, die zum Ändern des Verhaltens des WSARecvFrom-Funktionsaufrufs verwendet werden. Weitere Informationen finden Sie weiter unten im Abschnitt "Hinweise".
[out] lpFrom
Ein optionaler Zeiger auf einen Puffer, der die Quelladresse nach Abschluss des überlappenden Vorgangs enthält.
[in, out] lpFromlen
Ein Zeiger auf die Größe des "from"-Puffers in Bytes, der nur erforderlich ist, wenn lpFrom angegeben ist.
[in] lpOverlapped
Ein Zeiger auf eine WSAOVERLAPPED-Struktur (wird für nicht überlappte Sockets ignoriert).
[in] lpCompletionRoutine
Typ: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
Ein Zeiger auf die Vervollständigungsroutine, die aufgerufen wird, wenn der WSARecvFrom-Vorgang abgeschlossen wurde (bei nicht überlappten Sockets ignoriert).
Rückgabewert
Wenn kein Fehler auftritt und der Empfangsvorgang sofort abgeschlossen wurde, gibt WSARecvFrom 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 der Abschluss zu einem späteren Zeitpunkt angezeigt wird. Ein anderer Fehlercode gibt an, dass der überlappende Vorgang nicht erfolgreich initiiert wurde und keine Abschlussanzeige angezeigt wird.
Fehlercode | Bedeutung |
---|---|
Die virtuelle Verbindung wurde von der Remoteseite zurückgesetzt, die einen harten oder abbrechenden Schließvorgang ausgeführt hat. Die Anwendung sollte den Socket schließen, weil er nicht mehr verwendbar ist. Bei einem UPD-Datagrammsocket würde dieser Fehler darauf hindeuten, dass ein vorheriger Sendevorgang zu einer ICMP-Meldung "Port unreachable" geführt hat. | |
Die Parameter lpBuffers, lpFlags, lpFrom, lpNumberOfBytesRecvd, lpFromlen, lpOverlapped oder lpCompletionRoutine sind nicht vollständig in einem gültigen Teil des Benutzeradressraums enthalten: Der puffer lpFrom war zu klein, um die Peeradresse aufzunehmen. | |
Ein blockierter Windows Sockets 1.1-Aufruf wird ausgeführt, oder der Dienstanbieter verarbeitet noch eine Rückruffunktion. | |
Ein blockierender Windows Socket 1.1-Aufruf wurde über WSACancelBlockingCall abgebrochen. | |
Der Socket wurde nicht gebunden (z. B. mit bindung). | |
Die Nachricht war für den angegebenen Puffer zu groß, und (nur für unzuverlässige Protokolle) wurde jeder nachfolgende Teil der Nachricht verworfen, der nicht in den Puffer passte. | |
Fehler beim Netzwerksubsystem. | |
Für einen Datagrammsocket zeigt dieser Fehler an, dass die Gültigkeitsdauer abgelaufen ist. | |
Der Socket ist nicht verbunden (nur verbindungsorientierte Sockets). | |
Windows NT:
Überlappende Sockets: Es gibt zu viele ausstehende überlappende E/A-Anforderungen. Nicht überlappende Sockets: Der Socket ist als nicht blockiert gekennzeichnet, und der Empfangsvorgang kann nicht sofort abgeschlossen werden. |
|
Vor der Verwendung dieser Funktion muss ein erfolgreicher WSAStartup-Aufruf erfolgen. | |
Ein überlappender Vorgang wurde erfolgreich initiiert, und der Abschluss wird später angezeigt. | |
Der überlappende Vorgang wurde aufgrund des Schließens des Sockets abgebrochen. |
Hinweise
Die WSARecvFrom-Funktion bietet Funktionen über die Standardfunktion recvfrom hinaus in drei wichtigen Bereichen:
- Sie kann in Verbindung mit überlappenden Sockets verwendet werden, um überlappende Empfangsvorgänge auszuführen.
- Dadurch können mehrere Empfangspuffer angegeben werden, sodass sie auf den Punkt-/Gather-Typ von E/A anwendbar sind.
- Der lpFlags-Parameter ist sowohl ein Eingabe- als auch ein Ausgabeparameter, sodass Anwendungen den Ausgabezustand des MSG_PARTIAL Flagbits erkennen können. Beachten Sie, dass das MSG_PARTIAL-Flagbit nicht von allen Protokollen unterstützt wird.
Bei überlappenden Sockets wird diese Funktion verwendet, um einen oder mehrere Puffer zu posten, in denen eingehende Daten platziert werden, sobald sie in einem (möglicherweise verbundenen) Socket verfügbar werden, worauf die anwendungsspezifische Vervollständigungsanzeige (Aufruf der Vervollständigungsroutine oder Einstellung eines Ereignisobjekts) erfolgt. Wenn der Vorgang nicht sofort abgeschlossen wird, wird der endgültige Abschluss status über die Abschlussroutine oder WSAGetOverlappedResult abgerufen. Außerdem werden die von lpFrom und lpFromlen angegebenen Werte erst aktualisiert, wenn der Abschluss selbst angegeben ist. Anwendungen dürfen diese Werte erst verwenden oder stören, wenn sie aktualisiert wurden; Daher darf die Anwendung keine automatischen (also stapelbasierten) Variablen für diese Parameter verwenden.
Bei nicht überlappten Sockets ist die blockierende Semantik mit der der WSARecv-Standardfunktion identisch, und die Parameter lpOverlapped und lpCompletionRoutine werden ignoriert. Alle Daten, die bereits vom Transport empfangen und gepuffert wurden, werden in die Benutzerpuffer kopiert. Im Fall eines blockierenden Sockets, bei dem derzeit keine Daten empfangen und vom Transport gepuffert wurden, wird der Aufruf blockiert, bis Daten empfangen werden.
Die Puffer werden in der Reihenfolge gefüllt, in der sie in dem durch lpBuffers angegebenen Array angezeigt werden, und die Puffer werden so verpackt, dass keine Löcher erstellt werden.
Wenn diese Funktion auf überlappende Weise ausgeführt wird, liegt es in der Verantwortung des Winsock-Dienstanbieters, die WSABUF-Strukturen zu erfassen, bevor sie von diesem Aufruf zurückgegeben wird. Dadurch können Anwendungen stapelbasierte WSABUF-Arrays erstellen, auf die der lpBuffers-Parameter verweist.
Bei verbindungslosen Sockettypen wird die Adresse, von der die Daten stammen, in den durch lpFrom angegebenen Puffer kopiert. Der Wert, auf den von lpFromlen verwiesen wird, wird auf die Größe dieses Puffers initialisiert und bei Abschluss geändert, um die tatsächliche Größe der dort gespeicherten Adresse anzugeben. Wie bereits für überlappende Sockets angegeben, werden die Parameter lpFrom und lpFromlen erst nach Abschluss der überlappenden E/A aktualisiert. Der Speicher, auf den diese Parameter verweisen, muss daher für den Dienstanbieter verfügbar bleiben und kann nicht im Rahmen des Anwendungsstapels zugeordnet werden. Die Parameter lpFrom und lpFromlen werden für verbindungsorientierte Sockets ignoriert.
Bei Bytestreamsockets (z. B. Typ SOCK_STREAM) werden eingehende Daten in die Puffer platziert, bis:
- Die Puffer werden gefüllt.
- Die Verbindung ist geschlossen.
- Die intern gepufferten Daten sind erschöpft.
Der lpFlags-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 lpFlags-Parameter bestimmt. Letzteres wird mithilfe des bitweisen OR-Operators mit einem der in der folgenden Tabelle aufgeführten Werte erstellt.
Wert | Bedeutung |
---|---|
MSG_PEEK | Gibt eine Vorschau der eingehenden Daten an. Die Daten werden in den Puffer kopiert, aber nicht aus der Eingabewarteschlange entfernt. Dieses Flag ist nur für nicht überlappte Sockets gültig. |
MSG_OOB | Verarbeitet OOB-Daten. |
MSG_PARTIAL | Dieses Flag gilt nur für nachrichtenorientierte Sockets. Bei der Ausgabe gibt dieses Flag an, dass es sich bei den Daten um einen Teil der vom Absender übertragenen Nachricht handelt. Die restlichen Teile der Nachricht werden in nachfolgenden Empfangsvorgängen übertragen. Ein nachfolgender Empfangsvorgang mit deaktiviertem MSG_PARTIAL Flag gibt das Ende der Nachricht des Absenders an.
Als Eingabeparameter gibt dieses Flag an, dass der Empfangsvorgang abgeschlossen werden soll, auch wenn nur ein Teil einer Nachricht vom Dienstanbieter empfangen wurde. |
Bei nachrichtenorientierten Sockets wird das MSG_PARTIAL Bit im lpFlags-Parameter festgelegt, wenn eine Teilnachricht empfangen wird. Wenn eine vollständige Nachricht empfangen wird, wird MSG_PARTIAL in lpFlags gelöscht. Bei verzögerter Vervollständigung wird der wert, auf den von lpFlags verwiesen wird, nicht aktualisiert. Wenn die Vervollständigung angegeben wurde, sollte die Anwendung WSAGetOverlappedResult aufrufen und die Flags untersuchen, auf die der lpdwFlags-Parameter verweist.
Überlappende Socket-E/A
Wenn ein überlappender Vorgang sofort abgeschlossen wird, gibt WSARecvFrom den Wert 0 zurück, und der parameter lpNumberOfBytesRecvd wird mit der Anzahl der empfangenen Bytes aktualisiert, und die vom lpFlags-Parameter angezeigten Flagbits werden ebenfalls aktualisiert. Wenn der überlappende Vorgang erfolgreich initiiert wurde und später abgeschlossen wird, gibt WSARecvFromSOCKET_ERROR zurück und gibt fehlercode WSA_IO_PENDING an. In diesem Fall werden lpNumberOfBytesRecvd und lpFlags 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. Flagwerte werden entweder über den dwFlags-Parameter der Vervollständigungsroutine oder durch Untersuchen des lpdwFlags-Parameters von WSAGetOverlappedResult abgerufen.Die WSARecvFrom-Funktion kann innerhalb der Vervollständigungsroutine einer vorherigen WSARecv-, WSARecvFrom-, WSASend- oder WSASendTo-Funktion aufgerufen werden. Für einen bestimmten Socket werden E/A-Vervollständigungsroutinen nicht geschachtelt. So können zeitsensible Datenübertragungen vollständig in einem präventiven Kontext erfolgen.
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.
Wenn ein E/A-Vervollständigungsport verwendet wird und der lpCompletionRoutine-Parameter und der hEvent-ParameterNULL sind, ist das Ergebnis des Vorgangs ein Zeitplan für den E/A-Abschlussport. Dies geschieht bei allen erfolgreichen Vorgängen, unabhängig davon, ob die Vorgänge sofort abgeschlossen werden oder nicht.
Die Transportanbieter ermöglichen einer Anwendung das Aufrufen von Sende- und Empfangsvorgängen aus dem Kontext der Socket-E/A-Vervollständigungsroutine und garantieren, dass für einen bestimmten Socket E/A-Vervollständigungsroutinen 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 ist ein Platzhalter für einen anwendungsdefinierten oder bibliotheksdefinierten Funktionsnamen. DwError gibt die Vervollständigung status für den überlappenden Vorgang an, wie durch lpOverlapped angegeben. CbTransferred gibt die Anzahl der empfangenen Bytes an. Der dwFlags-Parameter enthält Informationen, die in lpFlags angezeigt worden wären, wenn der Empfangsvorgang sofort abgeschlossen worden wäre. 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. Bei Verwendung von WSAWaitForMultipleEvents werden alle Wartevervollständigungsroutinen aufgerufen, bevor die Wartezeit des warnbaren Threads mit dem Rückgabecode WSA_IO_COMPLETION. Die Vervollständigungsroutinen können in beliebiger Reihenfolge aufgerufen werden, nicht unbedingt in der gleichen Reihenfolge, in der die überlappenden Vorgänge abgeschlossen werden. Es wird jedoch garantiert, dass die gebuchten Puffer in der angegebenen Reihenfolge ausgefüllt werden.
Beispielcode
Im folgenden Beispiel wird die Verwendung der WSARecvFrom-Funktion veranschaulicht.#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>
int __cdecl main()
{
WSADATA wsaData;
WSABUF DataBuf;
WSAOVERLAPPED Overlapped;
SOCKET RecvSocket = INVALID_SOCKET;
struct sockaddr_in RecvAddr;
struct sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
u_short Port = 27015;
char RecvBuf[1024];
int BufLen = 1024;
DWORD BytesRecv = 0;
DWORD Flags = 0;
int err = 0;
int rc;
int retval = 0;
//-----------------------------------------------
// Initialize Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (rc != 0) {
/* Could not find a usable Winsock DLL */
wprintf(L"WSAStartup failed with error: %ld\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 == NULL) {
wprintf(L"WSACreateEvent failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
//-----------------------------------------------
// Create a receiver socket to receive datagrams
RecvSocket = WSASocket(AF_INET,
SOCK_DGRAM,
IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (RecvSocket == INVALID_SOCKET) {
/* Could not open a socket */
wprintf(L"WSASocket failed with error: %ld\n", WSAGetLastError());
WSACloseEvent(Overlapped.hEvent);
WSACleanup();
return 1;
}
//-----------------------------------------------
// Bind the socket to any address and the specified port.
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
rc = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
if (rc != 0) {
/* Bind to the socket failed */
wprintf(L"bind failed with error: %ld\n", WSAGetLastError());
WSACloseEvent(Overlapped.hEvent);
closesocket(RecvSocket);
WSACleanup();
return 1;
}
//-----------------------------------------------
// Call the recvfrom function to receive datagrams
// on the bound socket.
DataBuf.len = BufLen;
DataBuf.buf = RecvBuf;
wprintf(L"Listening for incoming datagrams on port=%d\n", Port);
rc = WSARecvFrom(RecvSocket,
&DataBuf,
1,
&BytesRecv,
&Flags,
(SOCKADDR *) & SenderAddr,
&SenderAddrSize, &Overlapped, NULL);
if (rc != 0) {
err = WSAGetLastError();
if (err != WSA_IO_PENDING) {
wprintf(L"WSARecvFrom failed with error: %ld\n", err);
WSACloseEvent(Overlapped.hEvent);
closesocket(RecvSocket);
WSACleanup();
return 1;
}
else {
rc = WSAWaitForMultipleEvents(1, &Overlapped.hEvent, TRUE, INFINITE, TRUE);
if (rc == WSA_WAIT_FAILED) {
wprintf(L"WSAWaitForMultipleEvents failed with error: %d\n", WSAGetLastError());
retval = 1;
}
rc = WSAGetOverlappedResult(RecvSocket, &Overlapped, &BytesRecv,
FALSE, &Flags);
if (rc == FALSE) {
wprintf(L"WSArecvFrom failed with error: %d\n", WSAGetLastError());
retval = 1;
}
else
wprintf(L"Number of received bytes = %d\n", BytesRecv);
wprintf(L"Finished receiving. Closing socket.\n");
}
}
//---------------------------------------------
// When the application is finished receiving, close the socket.
WSACloseEvent(Overlapped.hEvent);
closesocket(RecvSocket);
wprintf(L"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 unter Windows 8.1, Windows Server 2012 R2 und höher unterstützt.
Anforderungen
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 |