WSASend-Funktion (winsock2.h)
Die WSASend-Funktion sendet Daten auf einem verbundenen Socket.
Syntax
int WSAAPI WSASend(
[in] SOCKET s,
[in] LPWSABUF lpBuffers,
[in] DWORD dwBufferCount,
[out] LPDWORD lpNumberOfBytesSent,
[in] DWORD dwFlags,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
Parameter
[in] s
Ein Deskriptor, der einen 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 WSASend-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 Zahl in Bytes, die von diesem Aufruf gesendet wird, 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 verwendet werden, um das Verhalten des WSASend-Funktionsaufrufs zu ändern. Weitere Informationen finden Sie unter Verwenden von dwFlags im Abschnitt Hinweise.
[in] lpOverlapped
Ein Zeiger auf eine WSAOVERLAPPED-Struktur . Dieser Parameter 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 Sendevorgang abgeschlossen wurde. Dieser Parameter wird für nicht überlappte Sockets ignoriert.
Rückgabewert
Wenn kein Fehler auftritt und der Sendevorgang sofort abgeschlossen wurde, gibt WSASend 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 |
---|---|
Timeout- oder anderer Fehler. Die virtuelle Verbindung wurde beendet. | |
Bei einem Streamsocket wurde die virtuelle Verbindung von der Remoteseite zurückgesetzt. Die Anwendung sollte den Socket schließen, weil er nicht mehr verwendbar ist. Bei einem UDP-Datagrammsocket würde dieser Fehler darauf hindeuten, dass ein vorheriger Sendevorgang zu einer ICMP-Meldung "Port Unreachable" geführt hat. | |
Die Parameter lpBuffers, lpNumberOfBytesSent, lpOverlapped, lpCompletionRoutine sind nicht vollständig in einem gültigen Teil des Benutzeradressraums enthalten. | |
Ein blockierender Windows Socket 1.1-Aufruf wurde über WSACancelBlockingCall abgebrochen. | |
Ein blockierter Windows Sockets 1.1-Aufruf wird ausgeführt, oder der Dienstanbieter verarbeitet weiterhin eine Rückruffunktion. | |
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. | |
Bei einem Streamsocket wurde die Verbindung unterbrochen, weil die Keep-Alive-Aktivität einen Fehler erkennt, während der Vorgang ausgeführt wurde. Für einen Datagrammsocket zeigt dieser Fehler an, dass die Gültigkeitsdauer abgelaufen ist. | |
Der Windows Sockets-Anbieter meldet einen Puffer-Deadlock. | |
Der Socket ist nicht verbunden. | |
Der Deskriptor ist kein Socket. | |
MSG_OOB angegeben wurde, aber der Socket keine Streamart ist, z. B. typ SOCK_STREAM, werden OOB-Daten in der diesem Socket zugeordneten Kommunikationsdomäne nicht unterstützt, MSG_PARTIAL wird nicht unterstützt, oder der Socket ist unidirektional und unterstützt nur Empfangsvorgänge. | |
Der Socket wurde heruntergefahren. Es ist nicht möglich, WSASend für einen 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, der Ausführung des Befehls "SIO_FLUSH" in WSAIoctl oder des Threads, der die überlappende Anforderung initiiert hat, abgebrochen, bevor der Vorgang abgeschlossen wurde. Weitere Informationen finden Sie im Abschnitt mit Hinweisen. |
Bemerkungen
Die WSASend-Funktion bietet Funktionen über die Standardsendefunktion hinaus 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.
Ein socket, der von der Socketfunktion erstellt wurde, weist das überlappende Attribut als Standard auf. Ein Socket, der von der WSASocket-Funktion erstellt wird und der dwFlags-Parameter an WSASocket übergeben wird, mit dem WSA_FLAG_OVERLAPPED Bitsatz, weist das überlappende Attribut auf. Für Sockets mit dem überlappenden Attribut verwendet WSASend überlappende E/A, es sei denn, die Parameter lpOverlapped und lpCompletionRoutine sind NULL. In diesem Fall wird der Socket als nicht überlappender Socket behandelt. Es wird eine Vervollständigungsanzeige angezeigt, die die Vervollständigung einer Routine oder Einstellung eines Ereignisobjekts aufruft, 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.
Wenn sowohl lpOverlapped als auch lpCompletionRoutineNULL sind, wird der Socket in dieser Funktion als nicht überlappender Socket behandelt.
Bei nicht überlappenden Sockets werden die letzten beiden Parameter (lpOverlapped, lpCompletionRoutine) ignoriert, und WSASend übernimmt die gleiche blockierende Semantik wie send. Daten werden aus den Puffern in den Puffer des Transports kopiert. Wenn der Socket nicht blockierend und streamorientiert ist und nicht genügend Speicherplatz im Puffer des Transports vorhanden ist, wird WSASend zurückgegeben, wobei nur ein Teil der Puffer der Anwendung verbraucht wurde. Bei derselben Puffersituation und einem blockierenden Socket wird WSASend blockiert, bis der gesamte Inhalt des Anwendungspuffers verbraucht wurde.
Überschreiten Sie bei nachrichtenorientierten Sockets nicht die maximale Nachrichtengröße des zugrunde liegenden Anbieters, 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.
Windows Me/98/95: Die WSASend-Funktion unterstützt nicht mehr als 16 Puffer.
Verwenden von dwFlags
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 dem Routing unterliegen sollen. Ein Windows Sockets-Dienstanbieter kann dieses Flag ignorieren. |
MSG_OOB | Senden von OOB-Daten an einen Socket im Streamstil, z. B. nur SOCK_STREAM . |
MSG_PARTIAL | Gibt an, dass lpBuffers nur eine Teilmeldung 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 WSASend 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 WSASend SOCKET_ERROR zurück und gibt den 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 Abschlussroutine (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 ist, wenn er ein gültiges Ereignisobjekthandle enthält. Eine Anwendung kann WSAWaitForMultipleEvents oder WSAGetOverlappedResult verwenden, um auf 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 lpCompletionRoutine ungleich NULL ü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, würde zu unvorhersehbaren Ergebnissen führen.
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.
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 E/A-Vervollständigungsroutinen für einen bestimmten Socket nicht geschachtelt werden. Dadurch können zeitkritische Datenübertragungen vollständig in einem präemptiven Kontext erfolgen.
Das folgende C++-Codebeispiel ist ein Prototyp der Vervollständigungsroutine.
void CALLBACK CompletionROUTINE(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
Die CompletionRoutine-Funktion ist ein Platzhalter für einen anwendungsdefinierte oder bibliotheksdefinierte Funktionsnamen. Der dwError-Parameter gibt den Abschluss status für den überlappenden Vorgang an, wie durch lpOverlapped angegeben. cbTransferred gibt die Anzahl der gesendeten Bytes an. Derzeit sind keine Flagwerte definiert, und dwFlags ist 0 (null). Diese Funktion gibt keinen Wert zurück.
Die Rückgabe von dieser Funktion ermöglicht den Aufruf einer weiteren ausstehenden Vervollständigungsroutine für diesen Socket. Alle wartenden Vervollständigungsroutinen werden aufgerufen, bevor die Wartedauer des warnfähigen Threads mit einem Rückgabecode von WSA_IO_COMPLETION erfüllt wird. Die Vervollständigungsroutinen können in beliebiger Reihenfolge aufgerufen werden, nicht unbedingt in derselben Reihenfolge, in der die überlappenden Vorgänge abgeschlossen werden. Die bereitgestellten Puffer werden jedoch garantiert in derselben Reihenfolge gesendet, in der sie angegeben sind.
Die Reihenfolge der Aufrufe an WSASend ist auch die Reihenfolge, in der die Puffer an die Transportschicht übertragen werden. WSASend sollte nicht gleichzeitig für denselben streamorientierten Socket aus verschiedenen Threads aufgerufen werden, da einige Winsock-Anbieter eine große Sendeanforderung in mehrere Übertragungen aufteilen können. Dies kann dazu führen, dass unbeabsichtigte Daten von mehreren gleichzeitigen Sendeanforderungen auf demselben streamorientierten Socket überlappen.
Beispielcode
Im folgenden Codebeispiel wird veranschaulicht, wie die WSASend-Funktion im überlappenden E/A-Modus verwendet wird.#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
#define DATA_BUFSIZE 4096
#define SEND_COUNT 10
int __cdecl main()
{
WSADATA wsd;
struct addrinfo *result = NULL;
struct addrinfo hints;
WSAOVERLAPPED SendOverlapped;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET AcceptSocket = INVALID_SOCKET;
WSABUF DataBuf;
DWORD SendBytes;
DWORD Flags;
char buffer[DATA_BUFSIZE];
int err = 0;
int rc, i;
// Load Winsock
rc = WSAStartup(MAKEWORD(2, 2), &wsd);
if (rc != 0) {
printf("Unable to load Winsock: %d\n", rc);
return 1;
}
// Make sure the hints struct is zeroed out
SecureZeroMemory((PVOID) & hints, sizeof(struct addrinfo));
// Initialize the hints to obtain the
// wildcard bind address for IPv4
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
rc = getaddrinfo(NULL, "27015", &hints, &result);
if (rc != 0) {
printf("getaddrinfo failed with error: %d\n", rc);
return 1;
}
ListenSocket = socket(result->ai_family,
result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
return 1;
}
rc = bind(ListenSocket, result->ai_addr, (int) result->ai_addrlen);
if (rc == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
rc = listen(ListenSocket, 1);
if (rc == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
// Accept an incoming connection request
AcceptSocket = accept(ListenSocket, NULL, NULL);
if (AcceptSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
return 1;
}
printf("Client Accepted...\n");
// Make sure the SendOverlapped struct is zeroed out
SecureZeroMemory((PVOID) & SendOverlapped, sizeof (WSAOVERLAPPED));
// Create an event handle and setup the overlapped structure.
SendOverlapped.hEvent = WSACreateEvent();
if (SendOverlapped.hEvent == NULL) {
printf("WSACreateEvent failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
closesocket(AcceptSocket);
return 1;
}
DataBuf.len = DATA_BUFSIZE;
DataBuf.buf = buffer;
for (i = 0; i < SEND_COUNT; i++) {
rc = WSASend(AcceptSocket, &DataBuf, 1,
&SendBytes, 0, &SendOverlapped, NULL);
if ((rc == SOCKET_ERROR) &&
(WSA_IO_PENDING != (err = WSAGetLastError()))) {
printf("WSASend failed with error: %d\n", err);
break;
}
rc = WSAWaitForMultipleEvents(1, &SendOverlapped.hEvent, TRUE, INFINITE,
TRUE);
if (rc == WSA_WAIT_FAILED) {
printf("WSAWaitForMultipleEvents failed with error: %d\n",
WSAGetLastError());
break;
}
rc = WSAGetOverlappedResult(AcceptSocket, &SendOverlapped, &SendBytes,
FALSE, &Flags);
if (rc == FALSE) {
printf("WSASend failed with error: %d\n", WSAGetLastError());
break;
}
printf("Wrote %d bytes\n", SendBytes);
WSAResetEvent(SendOverlapped.hEvent);
}
WSACloseEvent(SendOverlapped.hEvent);
closesocket(AcceptSocket);
closesocket(ListenSocket);
freeaddrinfo(result);
WSACleanup();
return 0;
}
Windows Phone 8: Diese Funktion wird für Windows Phone Store-Apps ab Windows Phone 8 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 |