Red de conocimiento informático - Problemas con los teléfonos móviles - Operación de WSASend()

Operación de WSASend()

E/S de socket de superposición

Si la operación de superposición se completa inmediatamente, WSASend devuelve 0 y establece la variable señalada por lpNumberOfBytesSent en el número de bytes enviados. Si la operación de superposición tiene éxito y la inicialización se completa más tarde, WSASend devuelve SOCKET_ERROR y establece el código de error en WSA_IO_PENDING. En este momento, la variable señalada por lpNumberOfBytesSent no se actualizará. Una vez completada la IO superpuesta, la cantidad de bytes enviados se puede obtener de dos maneras: si se especifica una rutina de finalización (es decir, lpCompletionRoutine), la cantidad de bytes enviados se puede obtener del parámetro cbTransferred de la rutina de finalización. También se puede obtener llamando a WSAGetOverlappedResult y usando lpcbTransfer.

Tenga en cuenta que si un hilo sale, cualquier operación IO que emita se cancelará. Para sockets superpuestos, las operaciones asincrónicas pendientes pueden fallar si el subproceso se cierra antes de que se complete la operación; consulte ExitThread para obtener más información.

WSASend se puede llamar en la rutina de finalización de:

WSASend se puede llamar en la rutina de finalización de: WSARecv, WSARecvFrom, WSASend o WSASendTo. Esto le da a las transferencias de datos urgentes una mayor prioridad (lo que parece significar que si desea enviar datos más rápido, le brinda la oportunidad de enviar datos más rápido).

Los datos señalados por lpOverlapped siempre deben ser válidos durante una operación superpuesta (no querrás que aparezcan algunas variables locales allí :-)). Si hay varias operaciones de IO pendientes al mismo tiempo, cada operación debe tener una estructura WSAOVERLAPPED separada.

Si lpCompletionRoutine está vacío, cuando se complete la operación, si hEvent en lpOverlapped es un objeto de evento legal, el sistema configurará el evento como señalizado. Las aplicaciones de usuario pueden esperar este evento mediante WSAWaitForMultipleEvents o WSAGetOverlappedResult.

Si lpCompletionRoutine no es nulo, hEvent se ignora y se puede utilizar para pasar información de contexto a la rutina de finalización. Si la persona que llama establece una lpCompletionRoutine no nula y luego llama a WSAGetOverlappedResult en la misma IO superpuesta sin establecer el parámetro de WSAGetOverlappedResult en TRUE, hEvent no estará definido y esperar a que hEvent produzca resultados impredecibles. (Es decir, no desea utilizar la rutina de finalización y WSAGetOverlappedResult o hevnet al mismo tiempo).

La rutina de finalización aquí es la misma que la rutina de finalización de IO de archivos de Windows. La rutina de finalización se llama solo cuando el subproceso está en un estado de espera que puede alertar (como llamar a WSAWaitForMultipleEvents y establecer fAlertable en TRUE).

La capa del proveedor de transporte permite al usuario generar alertas en la rutina de finalización del socket superpuesto. La capa de transporte de datos (proveedor de transporte) permite a los usuarios emitir llamadas de envío y recepción en rutinas de finalización de sockets superpuestas, al tiempo que garantiza que las rutinas de finalización de IO no estén anidadas dentro de un socket determinado. De esta manera, se pueden priorizar las transferencias de datos urgentes.

El siguiente ejemplo de código C++ es un prototipo de la rutina de finalización:

El siguiente ejemplo de código C++ es un prototipo de la rutina de finalización.

void CALLBACK CompletionROUTINE(

EN DWORD dwError,

EN DWORD cbTransferred,

EN LPWSAOVERLAPPED lpOverlapped,

IN DWORD dwFlags

);

La rutina de finalización es solo un marcador de posición para funciones definidas por el usuario. (dwError representa el estado de finalización de IO superpuesta, especificado por lpOverlapped. cbTransferred es el número de bytes enviados. Esta función no tiene valor de retorno.

Después de regresar de esta función, se puede llamar a otra espera para este socket Rutinas de finalización. Todas las rutinas de finalización en espera se llaman antes de que se cumpla la espera del hilo alertable y se devuelva el código WSA_IO_COMPLETION. Sin embargo, se envían varios buffers en un orden superpuesto para garantizar que se envíen en el orden especificado. p>Si utiliza puertos de finalización, tenga en cuenta que el orden en el que se llama a WSASend es el orden en que se llena el búfer. No llame a funciones de WSASend en el mismo socket desde diferentes subprocesos al mismo tiempo, porque esto puede resultar. en un orden de datos impredecible en el búfer

Código de muestra

El siguiente código demuestra cómo utilizar la función WSASend de manera superpuesta.

#include

#include

#include

# incluya

#define DATA_BUFSIZE 4096

#define SEND_COUNT 10

void __cdecl main()

{

WSADATA wsd;

struct addrinfo * resultado = NULL,

sugerencias = ;

WSAOVERLAPPED SendOverlapped = ;

SOCKET ListenSocket = INVALID_SOCKET,

AcceptSocket = INVALID _SOCKET;

WSABUF DataBuf;

DWORD SendBytes, Flags;

búfer de caracteres[DATA_BUFSIZE ];

int err, rc, i;

// Cargar Winsock

rc = WSAStartup(MAKEWORD(2,2), &wsd);

if (rc != 0) {

fprintf(stderr, No se puede cargar Winsock: %d\n, rc);

return;

}

//Inicializar sugerencia para obtener

//Dirección de enlace comodín para IPv4

hintsai_family = AF_INET;

hindsai_socktype = SOCK_STREAM;

hintsai_protocol = IPPROTO_TCP;

hintsai_flags = AI_PASSIVE

rc =getaddrinfo(NULL, 27015, &resultado); p>if (rc != 0) {

fprintf(stderr, getaddrinfo falló: %d\n, rc );

return;

}

ListenSocket = socket(resultado->ai_family,

resultado->ai_socktype, resultado->ai_protocol);

if (ListenSocket == INVALID_SOCKET) {< / p>

fprintf(stderr, error en el socket: %d\n,

WSAGetLastError());

freeaddrinfo(resultado);

return;

}

rc = bind(ListenSocket, result->ai_addr,

(int)result->ai_addrlen);

if (rc == SOCKET_ERROR) {

fprintf(stderr, error de enlace: %d\n,

WSAGetLastError());

fre

eaddrinfo(resultado);

closesocket(ListenSocket);

return;

}

rc = escuchar(ListenSocket, 1);

if (rc == SOCKET_ ERROR) {

fprintf(stderr, error de escucha: %d\n,

WSAGetLastError());

freeaddrinfo(resultado);

closesocket(ListenSocket);

return;

}

//Aceptar conexión entrante solicitud

AcceptSocket = aceptar(ListenSocket, NULL, NULL);

if (AcceptSocket == INVALID_SOCKET) {

fprintf(stderr, aceptar error: %d\n,

WSAGetLastError());

freeaddrinfo( resultado);

closesocket(ListenSocket);

return;

}

printf(Cliente aceptado...\n);

// Crea un controlador de eventos y establece la estructura superpuesta.

SendOverlapped.hEvent =WSACreateEvent();

if (SendOverlapped.hEvent == NULL) {

fprintf(stderr, WSACreateEvent falló: %d\n ,

WSAGetLastError());

freeaddrinfo(resultado);

closesocket(ListenSocket);

closesocket(AcceptSocket);

retorno;

}

DataBuf.len = DATA_BUFSIZE;

DataBuf.buf = buffer;

para (i=0; i < SEND_COUNT ;i++) {

rc = WSASend(AcceptSocket, &DataBuf, 1,

&SendBytes, 0, &.SendOverlapped, NUL).

SendOverlapped, NULL);

if ( (rc == SOCKET_ERROR) &&

(WSA_IO_PENDING ! = (err = WSAGetLastError()))))){

fprintf(stderr, WSASend falló: %d\n, err);

break;

}

rc = WSAWaitForMultipleEvents(1, &SendOverlapped.hEvent, VERDADERO, INFINITO, VERDADERO);

if (rc == WSA_WAIT_FAILED) {

fprintf(stderr, WSAWaitForMultipleEvents falló: %d\n, WSAGetLastError());

break;

}

rc = WSAGetOverlappedResult(AcceptSocket, &SendOverlapped, &.SendBytes, FALSE, &Flags);

if (rc == FALSE ) {

fprintf(stderr, error en la operación WSASend: %d/n, WSAGetLastError());

break )

}

printf(Escribió %d bytes\n, SendBytes);

WSAResetEvent(SendOverlapped.hEvent);

}

WSACloseEvent( SendOverlapped.hEvent);

closesocket(AcceptSocket);

closesocket(ListenSocket);

freeaddrinfo(resultado);

WSACleanup();

regresar;

}