Compartilhar via


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
WSAECONNABORTED
O circuito virtual foi encerrado por causa do tempo limite ou outra falha.
WSAECONNRESET
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.
WSAEFAULT
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.
WSAEINTR
Uma chamada de bloqueio do Windows Socket 1.1 foi cancelada por meio de WSACancelBlockingCall.
WSAEINPROGRESS
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.
WSAEINVAL
O soquete não foi associado à associação ou o soquete não foi criado com o sinalizador sobreposto.
WSAEMSGSIZE
O soquete é orientado a mensagens e a mensagem é maior do que o máximo suportado pelo transporte subjacente.
WSAENETDOWN
O subsistema de rede falhou.
WSAENETRESET
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.
WSAENOBUFS
O provedor do Windows Sockets relata um deadlock de buffer.
WSAENOTCONN
O soquete não está conectado.
WSAENOTSOCK
O descritor não é um soquete.
WSAEOPNOTSUPP
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.
WSAESHUTDOWN
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.
WSAEWOULDBLOCK
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.

WSANOTINITIALISED
Uma chamada WSAStartup bem-sucedida deve ocorrer antes de usar essa função.
WSA_IO_PENDING
Uma operação sobreposta foi iniciada com êxito e a conclusão será indicada posteriormente.
WSA_OPERATION_ABORTED
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.
A função WSASend é usada para gravar dados de saída de um ou mais buffers em um soquete orientado à conexão especificado por s. Ele também pode ser usado, no entanto, em soquetes sem conexão que têm um endereço par padrão estipulado estabelecido por meio da função connect ou WSAConnect .

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.

Nota As opções de soquete SO_RCVTIMEO e SO_SNDTIMEO se aplicam somente a soquetes de bloqueio.
 
Se essa função for concluída de maneira sobreposta, será responsabilidade do provedor de serviços Winsock capturar as estruturas WSABUF antes de retornar dessa chamada. Isso permite que os aplicativos criem matrizes WSABUF baseadas em pilha apontadas pelo parâmetro lpBuffers .

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.

Nota A conclusão bem-sucedida de um WSASend não indica que os dados foram entregues com êxito.
 

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.
 
Nota Ao emitir uma chamada winsock de bloqueio, como WSASend com o parâmetro lpOverlapped definido como NULL, Winsock pode precisar aguardar um evento de rede antes que a chamada possa ser concluída. O Winsock executa uma espera alertável nessa situação, que pode ser interrompida por uma APC (chamada de procedimento assíncrono) agendada no mesmo thread. A emissão de outra chamada winsock de bloqueio dentro de um APC que interrompeu uma chamada Winsock de bloqueio contínuo no mesmo thread levará a um comportamento indefinido e nunca deve ser tentada por clientes Winsock.
 

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.
Nota Todas as E/S iniciadas por um determinado thread são canceladas quando esse thread é encerrado. Para soquetes sobrepostos, as operações assíncronas pendentes poderão falhar se o thread for fechado antes da conclusão das operações. Para obter mais informações, consulte ExitThread.
 
A função WSASend usando E/S sobreposta pode ser chamada de dentro da rotina de conclusão de uma função WSARecv, WSARecvFrom, WSASend ou WSASendTo anterior. Isso permite que transmissões de dados sensíveis ao tempo ocorram inteiramente em um contexto preemptivo.

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

Confira também

WSABUF

WSACloseEvent

Wsaconnect

Wsacreateevent

Wsagetoverlappedresult

WSAOVERLAPPED

Wsasocket

WSAWaitForMultipleEvents

Funções Winsock

Referência de Winsock

connect

send

socket