Compartilhar via


Função WSASendTo (winsock2.h)

A função WSASendTo envia dados para um destino específico, usando E/S sobreposta, quando aplicável.

Sintaxe

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
);

Parâmetros

[in] s

Um descritor que identifica um soquete (possivelmente conectado).

[in] lpBuffers

Um ponteiro para uma matriz de estruturas WSABUF . Cada estrutura WSABUF contém um ponteiro para um buffer e o comprimento do buffer, em bytes. Para um aplicativo Winsock, depois que a função WSASendTo é 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 de bytes enviados 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 WSASendTo .

[in] lpTo

Um ponteiro opcional para o endereço do soquete de destino na estrutura SOCKADDR .

[in] iTolen

O tamanho, em bytes, do endereço no parâmetro lpTo .

[in] lpOverlapped

Um ponteiro para uma estrutura WSAOVERLAPPED (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 (ignorado para soquetes não sobrepostos).

Retornar valor

Se nenhum erro ocorrer e a operação de envio tiver sido concluída imediatamente, WSASendTo 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
WSAEACCES
O endereço solicitado é um endereço de transmissão, mas o sinalizador apropriado não foi definido.
WSAEADDRNOTAVAIL
O endereço remoto não é um endereço válido (como ADDR_ANY).
WSAEAFNOSUPPORT
Os endereços na família especificada não podem ser usados com este soquete.
WSAECONNRESET
Para um soquete de datagrama UDP, esse erro indicaria que uma operação de envio anterior resultou em uma mensagem "Porta Inacessível" ICMP.
WSAEDESTADDRREQ
Endereço de destino necessário.
WSAEFAULT
Os parâmetros lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent ou lpCompletionRoutine não fazem parte do espaço de endereço do usuário ou o parâmetro lpTo é muito pequeno.
WSAEHOSTUNREACH
Uma operação de soquete foi tentada em um host inacessível.
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.
WSAEINTR
Uma chamada de bloqueio do Windows Socket 1.1 foi cancelada por meio de WSACancelBlockingCall.
WSAEINVAL
O soquete não foi associado à associação ou o soquete não é 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 datagrama, este erro indica que a vida útil venceu.
WSAENETUNREACH
A rede não pode ser alcançada através deste host neste momento.
WSAENOBUFS
O provedor do Windows Sockets relata um deadlock de buffer.
WSAENOTCONN
O soquete não está conectado (somente soquetes orientados à conexão).
WSAENOTSOCK
O descritor não é um soquete.
WSAESHUTDOWN
O soquete foi desligado; não é possível usar WSASendTo em um soquete após o desligamento ter sido invocado com a definição de 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 ou à execução do comando SIO_FLUSH no WSAIoctl.

Comentários

A função WSASendTo fornece recursos aprimorados sobre a função sendto 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 WSASendTo normalmente é usada em um soquete sem conexão especificado por s para enviar um datagrama contido em um ou mais buffers para um soquete par específico identificado pelo parâmetro lpTo . Mesmo que o soquete sem conexão tenha sido conectado anteriormente usando a função connect a um endereço específico, o lpTo substituirá o endereço de destino somente para esse datagrama específico. Em um soquete orientado a conexão, os parâmetros lpTo e iToLen são ignorados; Nesse caso, o WSASendTo é equivalente a WSASend.

Para soquetes sobrepostos (criados usando WSASocket com sinalizador WSA_FLAG_OVERLAPPED) o envio de dados usa E/S sobreposta, a menos que lpOverlapped e lpCompletionRoutine sejam NULL , nesse caso, o soquete é tratado como um soquete não sobreposto. Uma indicação de conclusão ocorrerá (invocando a rotina de conclusão ou a 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.

Nota Se um soquete for aberto, uma chamada setsockopt será feita e, em seguida, uma chamada sendto será feita, o Windows Sockets executará uma chamada de função de associação implícita.
 
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 WSASendTo adota a mesma semântica de bloqueio que o envio. Os dados são copiados dos buffers para o buffer de transporte. Se o soquete não estiver sendo desbloqueado e orientado a fluxo e não houver espaço suficiente no buffer do transporte, WSASendTo retornará com apenas parte dos buffers do aplicativo que foram consumidos. Dada a mesma situação de buffer e um soquete de bloqueio, o WSASendTo será bloqueado até que todo o conteúdo do buffer do aplicativo tenha sido consumido.

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, é necessário ter cuidado para não exceder o tamanho máximo da mensagem do transporte 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.

Se o soquete não estiver associado, os valores exclusivos serão atribuídos à associação local pelo sistema e o soquete será marcado como associado.

Se o soquete estiver conectado, a função getsockname poderá ser usada para determinar o endereço IP local e a porta associada ao soquete.

Se o soquete não estiver conectado, o
A função getsockname pode ser usada para determinar o número da porta local associado ao soquete, mas o endereço IP retornado é definido como o endereço curinga do protocolo fornecido (por exemplo, INADDR_ANY ou "0.0.0.0" para IPv4 e IN6ADDR_ANY_INIT ou "::" para IPv6).

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

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 Socket pode optar por ignorar esse sinalizador.
MSG_OOB Enviar dados OOB (soquete no estilo de fluxo, como somente SOCK_STREAM ).
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 WSASendTo , 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íncrona) agendada no mesmo thread. Emitir 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 tentado pelos clientes winsock.
 

E/S de soquete sobreposto

Se uma operação sobreposta for concluída imediatamente, WSASendTo 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 WSASendTo 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 podem falhar se o thread for fechado antes da conclusão das operações. Consulte ExitThread para obter mais informações.
 
A função WSASendTo 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 simultaneamente pendentes, 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 chama posteriormente 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 tentar 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 invocada.

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 em um contexto preemptivo.

O protótipo da rotina de conclusão é o seguinte.


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. O parâmetro 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.

Retornar dessa função permite a invocação de outra rotina de conclusão pendente para esse soquete. Todas as rotinas de conclusão de espera são chamadas antes que a espera do thread alertável seja atendida 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 especificada.

Código de exemplo

O exemplo a seguir demonstra o uso da função WSASendTo usando um objeto de evento.
#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: 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

WSACloseEvent

Wsacreateevent

Wsagetoverlappedresult

Wsasocket

WSAWaitForMultipleEvents

Funções Winsock

Referência de Winsock