Função WSASend (winsock2.h)
A função WSASend envia dados em um soquete conectado.
Sintaxe
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
);
Parâmetros
[in] s
Um descritor que identifica um soquete conectado.
[in] lpBuffers
Um ponteiro para uma matriz de estruturas WSABUF . Cada estrutura WSABUF contém um ponteiro para um buffer e o comprimento, em bytes, do buffer. Para um aplicativo Winsock, depois que a função WSASend é chamada, o sistema possui esses buffers e o aplicativo pode não acessá-los. Essa matriz deve permanecer válida durante a operação de envio.
[in] dwBufferCount
O número de estruturas WSABUF na matriz lpBuffers .
[out] lpNumberOfBytesSent
Um ponteiro para o número, em bytes, enviado por essa chamada se a operação de E/S for concluída imediatamente.
Use NULL para esse parâmetro se o parâmetro lpOverlapped não for NULL para evitar resultados potencialmente incorretos. Esse parâmetro só poderá ser NULL se o parâmetro lpOverlapped não for NULL.
[in] dwFlags
Os sinalizadores usados para modificar o comportamento da chamada de função WSASend . Para obter mais informações, consulte Usando dwFlags na seção Comentários.
[in] lpOverlapped
Um ponteiro para uma estrutura WSAOVERLAPPED . Esse parâmetro é ignorado para soquetes não sobrepostos.
[in] lpCompletionRoutine
Tipo: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
Um ponteiro para a rotina de conclusão chamado quando a operação de envio foi concluída. Esse parâmetro é ignorado para soquetes não sobrepostos.
Retornar valor
Se nenhum erro ocorrer e a operação de envio tiver sido concluída imediatamente, WSASend retornará zero. Nesse caso, a rotina de conclusão já terá sido agendada para ser chamada quando o thread de chamada estiver no estado alertável. Caso contrário, um valor de SOCKET_ERROR será retornado e um código de erro específico poderá ser recuperado chamando WSAGetLastError. O código de erro WSA_IO_PENDING indica que a operação sobreposta foi iniciada com êxito e que a conclusão será indicada posteriormente. Qualquer outro código de erro indica que a operação sobreposta não foi iniciada com êxito e nenhuma indicação de conclusão ocorrerá.
Código do erro | Significado |
---|---|
O circuito virtual foi encerrado por causa do tempo limite ou outra falha. | |
Para um soquete de fluxo, o circuito virtual foi redefinido pelo lado remoto. O aplicativo deve fechar o soquete porque ele não pode ser mais usado. Para um soquete de datagrama UDP, esse erro indicaria que uma operação de envio anterior resultou em uma mensagem "Porta Inacessível" ICMP. | |
O parâmetro lpBuffers, lpNumberOfBytesSent, lpOverlapped, lpCompletionRoutine não está totalmente contido em uma parte válida do espaço de endereço do usuário. | |
Uma chamada de bloqueio do Windows Socket 1.1 foi cancelada por meio de WSACancelBlockingCall. | |
Uma chamada de bloqueio do Windows Sockets 1.1 está em andamento ou o provedor de serviços ainda está processando uma função de retorno de chamada. | |
O soquete não foi associado à associação ou o soquete não foi criado com o sinalizador sobreposto. | |
O soquete é orientado a mensagens e a mensagem é maior do que o máximo suportado pelo transporte subjacente. | |
O subsistema de rede falhou. | |
Para um soquete de fluxo, a conexão foi interrompida devido à atividade keep alive detectar uma falha enquanto a operação estava em andamento. Para um soquete de datagrama, este erro indica que a vida útil venceu. | |
O provedor do Windows Sockets relata um deadlock de buffer. | |
O soquete não está conectado. | |
O descritor não é um soquete. | |
MSG_OOB foi especificado, mas o soquete não é estilo de fluxo, como tipo SOCK_STREAM, não há suporte para dados OOB no domínio de comunicação associado a esse soquete, MSG_PARTIAL não tem suporte ou o soquete é unidirecional e dá suporte apenas a operações de recebimento. | |
O soquete foi desligado; não é possível que o WSASend em um soquete após o desligamento tenha sido invocado com a definição de como SD_SEND ou SD_BOTH. | |
Windows NT:
Soquetes sobrepostos: há muitas solicitações de E/S sobrepostas pendentes. Soquetes não sobrepostos: o soquete é marcado como não desbloqueio e a operação de envio não pode ser concluída imediatamente. |
|
Uma chamada WSAStartup bem-sucedida deve ocorrer antes de usar essa função. | |
Uma operação sobreposta foi iniciada com êxito e a conclusão será indicada posteriormente. | |
A operação sobreposta foi cancelada devido ao fechamento do soquete, à execução do comando "SIO_FLUSH" no WSAIoctl ou ao thread que iniciou a solicitação sobreposta encerrada antes da conclusão da operação. Para obter mais informações, consulte a seção Comentários. |
Comentários
A função WSASend fornece funcionalidade além da função de envio padrão em duas áreas importantes:
- Ele pode ser usado em conjunto com soquetes sobrepostos para executar operações de envio sobrepostas.
- Ele permite que vários buffers de envio sejam especificados, tornando-o aplicável ao tipo de E/S de dispersão/coleta.
Um soquete criado pela função de soquete terá o atributo sobreposto como padrão. Um soquete criado pela função WSASocket com o parâmetro dwFlags passado para WSASocket com o conjunto de bits WSA_FLAG_OVERLAPPED terá o atributo sobreposto. Para soquetes com o atributo sobreposto, o WSASend usa E/S sobreposta, a menos que os parâmetros lpOverlapped e lpCompletionRoutine sejam NULL. Nesse caso, o soquete é tratado como um soquete não sobreposto. Ocorrerá uma indicação de conclusão, invocando a conclusão de uma rotina ou configuração de um objeto de evento, quando os buffers forem consumidos pelo transporte. Se a operação não for concluída imediatamente, o status de conclusão final será recuperado por meio da rotina de conclusão ou WSAGetOverlappedResult.
Se lpOverlapped e lpCompletionRoutine forem NULL, o soquete nessa função será tratado como um soquete não sobreposto.
Para soquetes não sobrepostos, os dois últimos parâmetros (lpOverlapped, lpCompletionRoutine) são ignorados e o WSASend adota a mesma semântica de bloqueio que o envio. Os dados são copiados dos buffers para o buffer do transporte. Se o soquete não estiver bloqueando e orientado a fluxo e não houver espaço suficiente no buffer do transporte, o WSASend retornará com apenas parte dos buffers do aplicativo sendo consumidos. Dada a mesma situação de buffer e um soquete de bloqueio, o WSASend será bloqueado até que todo o conteúdo do buffer do aplicativo seja consumido.
Para soquetes orientados a mensagens, não exceda o tamanho máximo da mensagem do provedor subjacente, que pode ser obtido obtendo o valor da opção de soquete SO_MAX_MSG_SIZE. Se os dados forem muito longos para passar atomicamente pelo protocolo subjacente, o erro WSAEMSGSIZE será retornado e nenhum dado será transmitido.
Windows Me/98/95: A função WSASend não dá suporte a mais de 16 buffers.
Usando dwFlags
O parâmetro dwFlags pode ser usado para influenciar o comportamento da invocação de função além das opções especificadas para o soquete associado. Ou seja, a semântica dessa função é determinada pelas opções de soquete e pelo parâmetro dwFlags . Este último é construído usando o operador OR bit a bit com qualquer um dos valores listados na tabela a seguir.Valor | Significado |
---|---|
MSG_DONTROUTE | Especifica que os dados não devem estar sujeitos ao roteamento. Um provedor de serviços do Windows Sockets pode optar por ignorar esse sinalizador. |
MSG_OOB | Envie dados OOB em um soquete no estilo de fluxo, como SOCK_STREAM apenas. |
MSG_PARTIAL | Especifica que lpBuffers contém apenas uma mensagem parcial. Lembre-se de que o código de erro WSAEOPNOTSUPP será retornado por transportes que não dão suporte a transmissões parciais de mensagens. |
E/S de soquete sobreposta
Se uma operação sobreposta for concluída imediatamente, WSASend retornará um valor igual a zero e o parâmetro lpNumberOfBytesSent será atualizado com o número de bytes enviados. Se a operação sobreposta for iniciada com êxito e for concluída posteriormente, o WSASend retornará SOCKET_ERROR e indicará o código de erro WSA_IO_PENDING. Nesse caso, lpNumberOfBytesSent não é atualizado. Quando a operação sobreposta conclui, a quantidade de dados transferidos é indicada por meio do parâmetro cbTransferred na rotina de conclusão (se especificada) ou por meio do parâmetro lpcbTransfer em WSAGetOverlappedResult.O parâmetro lpOverlapped deve ser válido durante a operação sobreposta. Se várias operações de E/S estiverem pendentes simultaneamente, cada uma deverá referenciar uma estrutura WSAOVERLAPPED separada.
Se o parâmetro lpCompletionRoutine for NULL, o parâmetro hEvent de lpOverlapped será sinalizado quando a operação sobreposta for concluída se contiver um identificador de objeto de evento válido. Um aplicativo pode usar WSAWaitForMultipleEvents ou WSAGetOverlappedResult para aguardar ou sondar o objeto de evento.
Se lpCompletionRoutine não for NULL, o parâmetro hEvent será ignorado e poderá ser usado pelo aplicativo para passar informações de contexto para a rotina de conclusão. Um chamador que passa um lpCompletionRoutine não NULL e, posteriormente, chama WSAGetOverlappedResult para a mesma solicitação de E/S sobreposta pode não definir o parâmetro fWait para essa invocação de WSAGetOverlappedResult como TRUE. Nesse caso, o uso do parâmetro hEvent é indefinido e a tentativa de aguardar o parâmetro hEvent produziria resultados imprevisíveis.
A rotina de conclusão segue as mesmas regras estipuladas para rotinas de conclusão de E/S de arquivo do Windows. A rotina de conclusão não será invocada até que o thread esteja em um estado de espera alertável, como pode ocorrer quando a função WSAWaitForMultipleEvents com o parâmetro fAlertable definido como TRUE for invocado.
Os provedores de transporte permitem que um aplicativo invoque operações de envio e recebimento de dentro do contexto da rotina de conclusão de E/S do soquete e garantam que, para um determinado soquete, as rotinas de conclusão de E/S não serão aninhadas. Isso permite que transmissões de dados sensíveis ao tempo ocorram inteiramente dentro de um contexto preemptivo.
O exemplo de código C++ a seguir é um protótipo da rotina de conclusão.
void CALLBACK CompletionROUTINE(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
A função CompletionRoutine é um espaço reservado para um nome de função definido pelo aplicativo ou definido pela biblioteca. O parâmetro dwError especifica o status de conclusão para a operação sobreposta, conforme indicado por lpOverlapped. cbTransferred especifica o número de bytes enviados. Atualmente, não há valores de sinalizador definidos e dwFlags será zero. Essa função não retorna um valor.
O retorno dessa função permite a invocação de outra rotina de conclusão pendente para esse soquete. Todas as rotinas de conclusão em espera são chamadas antes que a espera do thread alertável seja satisfeita com um código de retorno de WSA_IO_COMPLETION. As rotinas de conclusão podem ser chamadas em qualquer ordem, não necessariamente na mesma ordem em que as operações sobrepostas são concluídas. No entanto, os buffers postados têm a garantia de serem enviados na mesma ordem em que são especificados.
A ordem das chamadas feitas ao WSASend também é a ordem na qual os buffers são transmitidos para a camada de transporte. O WSASend não deve ser chamado no mesmo soquete orientado a fluxo simultaneamente de threads diferentes, pois alguns provedores Winsock podem dividir uma solicitação de envio grande em várias transmissões, o que pode levar à intercalação de dados não intencionais de várias solicitações de envio simultâneas no mesmo soquete orientado a fluxo.
Código de exemplo
O exemplo de código a seguir mostra como usar a função WSASend no modo de E/S sobreposto.#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: essa função tem suporte para aplicativos da Windows Phone Store no Windows Phone 8 e posterior.
Windows 8.1 e Windows Server 2012 R2: essa função tem suporte para aplicativos da Windows Store em Windows 8.1, Windows Server 2012 R2 e posteriores.
Requisitos
Requisito | Valor |
---|---|
Cliente mínimo com suporte | Windows 8.1, Windows Vista [aplicativos da área de trabalho | Aplicativos UWP] |
Servidor mínimo com suporte | Windows Server 2003 [aplicativos da área de trabalho | Aplicativos UWP] |
Plataforma de Destino | Windows |
Cabeçalho | winsock2.h |
Biblioteca | Ws2_32.lib |
DLL | Ws2_32.dll |