Función sendto (winsock.h)

La función sendto envía datos a un destino específico.

Sintaxis

int sendto(
  [in] SOCKET         s,
  [in] const char     *buf,
  [in] int            len,
  [in] int            flags,
  [in] const sockaddr *to,
  [in] int            tolen
);

Parámetros

[in] s

Descriptor que identifica un socket (posiblemente conectado).

[in] buf

Puntero a un búfer que contiene los datos que se van a transmitir.

[in] len

Longitud, en bytes, de los datos a los que apunta el parámetro buf .

[in] flags

Conjunto de marcas que especifican la forma en que se realiza la llamada.

[in] to

Puntero opcional a una estructura sockaddr que contiene la dirección del socket de destino.

[in] tolen

Tamaño, en bytes, de la dirección a la que apunta el parámetro .

Valor devuelto

Si no se produce ningún error, sendto devuelve el número total de bytes enviados, que puede ser menor que el número indicado por len. De lo contrario, se devuelve un valor de SOCKET_ERROR y se puede recuperar un código de error específico mediante una llamada a WSAGetLastError.

Código de error Significado
WSANOTINITIALISED
Debe producirse una llamada WSAStartup correcta antes de usar esta función.
WSAENETDOWN
Error en el subsistema de red.
WSAEACCES
La dirección solicitada es una dirección de difusión, pero no se ha establecido la marca adecuada. Llame a setsockopt con el parámetro SO_BROADCAST para permitir el uso de la dirección de difusión.
WSAEINVAL
Se especificó una marca desconocida o MSG_OOB se especificó para un socket con SO_OOBINLINE habilitado.
WSAEINTR
Se canceló una llamada de Bloqueo de Windows Sockets 1.1 a través de WSACancelBlockingCall.
WSAEINPROGRESS
Una llamada de Bloqueo de Windows Sockets 1.1 está en curso o el proveedor de servicios sigue procesando una función de devolución de llamada.
WSAEFAULT
Los parámetros buf o to no forman parte del espacio de direcciones del usuario o el parámetro tolen es demasiado pequeño.
WSAENETRESET
Se ha interrumpido la conexión debido a que la actividad para mantener activa la conexión detectó un error durante la operación.
WSAENOBUFS
No hay espacio disponible en el búfer.
WSAENOTCONN
El socket no está conectado (solo sockets orientados a la conexión).
WSAENOTSOCK
El descriptor no es un socket.
WSAEOPNOTSUPP
MSG_OOB se especificó, pero el socket no es de tipo SOCK_STREAM, los datos OOB no se admiten en el dominio de comunicación asociado a este socket, o el socket es unidireccional y solo admite operaciones de recepción.
WSAESHUTDOWN
El socket se ha apagado; no es posible enviar a en un socket después de que se haya invocado el apagado con cómo se establece en SD_SEND o SD_BOTH.
WSAEWOULDBLOCK
El socket está marcado como de no bloqueo y la operación solicitada supondría un bloqueo.
WSAEMSGSIZE
El socket está orientado a mensajes y el mensaje es mayor que el máximo admitido por el transporte subyacente.
WSAEHOSTUNREACH
No se puede acceder al host remoto desde este host en este momento.
WSAECONNABORTED
Se finalizó el circuito virtual debido a un tiempo de espera agotado u otro error. La aplicación debería cerrar el socket porque ya no se puede usar.
WSAECONNRESET
El lado remoto que ejecuta un cierre firme o de anulación restableció el circuito virtual. En el caso de los sockets UDP, el host remoto no pudo entregar un datagrama UDP enviado previamente y respondió con un paquete ICMP "Puerto inaccesible". La aplicación debería cerrar el socket porque ya no se puede usar.
WSAEADDRNOTAVAIL
La dirección remota no es una dirección válida, por ejemplo, ADDR_ANY.
WSAEAFNOSUPPORT
Las direcciones de la familia especificada no se pueden usar con este socket.
WSAEDESTADDRREQ
Se requiere una dirección de destino.
WSAENETUNREACH
La red no se puede alcanzar desde este host en estos momentos.
WSAEHOSTUNREACH
Se intentó realizar una operación de socket a un host inalcanzable.
WSAETIMEDOUT
Se ha quitado la conexión, debido a un error de red o porque el sistema en el otro extremo se ha reducido sin previo aviso.

Comentarios

La función sendto se usa para escribir datos salientes en un socket. En el caso de los sockets orientados a mensajes, se debe tener cuidado de no superar el tamaño máximo del paquete de las subredes subyacentes, que se puede obtener mediante getsockopt para recuperar el valor de la opción de socket SO_MAX_MSG_SIZE. Si los datos son demasiado largos para pasarse atómicamente a través del protocolo subyacente, se devuelve el error WSAEMSGSIZE y no se transmite ningún dato.

El parámetro to puede ser cualquier dirección válida en la familia de direcciones del socket, incluida una difusión o cualquier dirección de multidifusión. Para enviar a una dirección de difusión, una aplicación debe haber usado setsockopt con SO_BROADCAST habilitado. De lo contrario, sendto producirá un error con el código de error WSAEACCES. Para TCP/IP, una aplicación puede enviar a cualquier dirección de multidifusión (sin convertirse en miembro del grupo).

Nota Si se abre un socket, se realiza una llamada a setsockopt y, a continuación, se realiza una llamada sendto , Windows Sockets realiza una llamada de función de enlace implícita.
 
Si el socket no está enlazado, el sistema asigna valores únicos a la asociación local y el socket se marca como enlazado. Si el socket está conectado, se puede usar la función getsockname para determinar la dirección IP local y el puerto asociados al socket.

Si el socket no está conectado,
La función getsockname se puede usar para determinar el número de puerto local asociado al socket, pero la dirección IP devuelta se establece en la dirección comodín del protocolo especificado (por ejemplo, INADDR_ANY o "0.0.0.0" para IPv4 y IN6ADDR_ANY_INIT o "::" para IPv6).

La finalización correcta de un sendto no indica que los datos se entregaron correctamente.

La función sendto se usa normalmente en un socket sin conexión para enviar un datagrama a un socket del mismo nivel específico identificado por el parámetro to . Incluso si el socket sin conexión se ha conectado previamente a una dirección específica, el parámetro to invalida la dirección de destino solo para ese datagrama concreto. En un socket orientado a la conexión, se omiten los parámetros tolen y tolen , lo que hace que sendto sea equivalente al envío.

Nota Al emitir una llamada de Winsock de bloqueo como sendto, Winsock puede que tenga que esperar un evento de red antes de que se pueda completar la llamada. Winsock realiza una espera alertable en esta situación, que se puede interrumpir mediante una llamada de procedimiento asincrónica (APC) programada en el mismo subproceso. La emisión de otra llamada winsock de bloqueo dentro de un APC que interrumpió una llamada de Winsock de bloqueo en curso en el mismo subproceso provocará un comportamiento indefinido y los clientes winsock nunca deben intentarlo.
 

Código de ejemplo

En el ejemplo siguiente se muestra el uso de la función sendto .
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

int main()
{

    int iResult;
    WSADATA wsaData;

    SOCKET SendSocket = INVALID_SOCKET;
    sockaddr_in RecvAddr;

    unsigned short Port = 27015;

    char SendBuf[1024];
    int BufLen = 1024;

    //----------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    //---------------------------------------------
    // Create a socket for sending data
    SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (SendSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //---------------------------------------------
    // Set up the RecvAddr structure with the IP address of
    // the receiver (in this example case "192.168.1.1")
    // and the specified port number.
    RecvAddr.sin_family = AF_INET;
    RecvAddr.sin_port = htons(Port);
    RecvAddr.sin_addr.s_addr = inet_addr("192.168.1.1");

    //---------------------------------------------
    // Send a datagram to the receiver
    wprintf(L"Sending a datagram to the receiver...\n");
    iResult = sendto(SendSocket,
                     SendBuf, BufLen, 0, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
    if (iResult == SOCKET_ERROR) {
        wprintf(L"sendto failed with error: %d\n", WSAGetLastError());
        closesocket(SendSocket);
        WSACleanup();
        return 1;
    }
    //---------------------------------------------
    // When the application is finished sending, close the socket.
    wprintf(L"Finished sending. Closing socket.\n");
    iResult = closesocket(SendSocket);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"closesocket failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //---------------------------------------------
    // Clean up and quit.
    wprintf(L"Exiting.\n");
    WSACleanup();
    return 0;
}


Para sockets que usan IP (versión 4)

Para enviar una difusión (solo en un SOCK_DGRAM), la dirección a la que apunta el parámetro to se puede construir para contener la dirección IPv4 especial INADDR_BROADCAST (definida en Winsock2.h), junto con el número de puerto previsto. Si la dirección a la que apunta el parámetro contiene la dirección INADDR_BROADCAST y el puerto previsto, la difusión se enviará en todas las interfaces a ese puerto.

Si la difusión solo se debe enviar en una interfaz específica, la dirección a la que apunta el parámetro to debe contener la dirección de difusión de subred para la interfaz y el puerto previsto. Por ejemplo, una dirección de red IPv4 de 192.168.1.0 con una máscara de subred de 255.255.255.0 usaría una dirección de difusión de subred de 192.168.1.255.

Por lo general, se desaconseja que un datagrama de difusión supere el tamaño en el que pueda producirse una fragmentación, lo que implica que la parte de datos del datagrama (excluyendo los encabezados) no debe superar los 512 bytes.

Si no hay espacio de búfer disponible en el sistema de transporte para contener los datos que se van a transmitir, sendto se bloqueará a menos que el socket se haya colocado en un modo de bloqueo. En los sockets orientados a flujos, el número de bytes escritos puede estar entre 1 y la longitud solicitada, en función de la disponibilidad del búfer en los sistemas cliente y servidor. La función select, WSAAsyncSelect o WSAEventSelect se puede usar para determinar cuándo es posible enviar más datos.

Llamar a sendto con un len de cero está permitido y devolverá cero como un valor válido. En el caso de los sockets orientados a mensajes, se envía un datagrama de transporte de longitud cero.

El parámetro flags se puede usar para influir en el comportamiento de la invocación de función más allá de las opciones especificadas para el socket asociado. La semántica de esta función viene determinada por las opciones de socket y el parámetro flags . Este último se construye mediante el operador OR bit a bit con cualquiera de los valores siguientes.

Valor Significado
MSG_DONTROUTE Especifica que los datos no deben estar sujetos a enrutamiento. Un proveedor de servicios de Windows Sockets puede optar por omitir esta marca.
MSG_OOB Envía datos OOB (socket de estilo de flujo, como solo SOCK_STREAM).
 

Windows Phone 8: esta función es compatible con las aplicaciones de Windows Phone Store en Windows Phone 8 y versiones posteriores.

Windows 8.1 y Windows Server 2012 R2: esta función es compatible con las aplicaciones de la Tienda Windows en Windows 8.1, Windows Server 2012 R2 y versiones posteriores.

Requisitos

   
Cliente mínimo compatible Windows 8.1, Windows Vista [aplicaciones de escritorio | Aplicaciones para UWP]
Servidor mínimo compatible Windows Server 2003 [aplicaciones de escritorio | aplicaciones para UWP]
Plataforma de destino Windows
Encabezado winsock.h (incluya Winsock2.h)
Library Ws2_32.lib
Archivo DLL Ws2_32.dll

Consulte también

WSAAsyncSelect

WSAEventSelect

Funciones winsock

Referencia de Winsock

recv

recvfrom

select

enviar

socket