< Overlapped Model & Example | Winsock2 I/O Method Main | Overlapped I/O with Callback Example >


 

 

Winsock 2 I/O Methods 5 Part 7

 

 

What do we have in this chapter 5 part 7?

  1. The Overlapped Example Using AcceptEx()

  2. Running the Server and Client Program

 

The Overlapped Example Using AcceptEx()

 

The following program example demonstrates the use of AcceptEx() for overlapped model. Create a new empty Win32 console mode application and add the project/solution name.

 

The Overlapped IO Model: The overlapped example using AcceptEx()

 

Add the following source code.

 

// Description:

//

//    This sample illustrates how to develop a simple echo server Winsock

//    application using the Overlapped I/O model with event notification. This

//    sample is implemented as a console-style application and simply prints

//    messages when connections are established and removed from the server.

//    The application listens for TCP connections on port 5150 and accepts them

//    as they arrive. When this application receives data from a client, it

//    simply echoes (this is why we call it an echo server) the data back in

//    it's original form until the client closes the connection.

//

//    Note: There are no command line options for this sample.

//

// Link to ws2_32.lib

#include <winsock2.h>

// Link to mswsock.lib

#include <mswsock.h>

#include <windows.h>

#include <stdio.h>

 

#define PORT 5150

#define DATA_BUFSIZE 8192

 

typedef struct _SOCKET_INFORMATION {

   CHAR Buffer[DATA_BUFSIZE];

   WSABUF DataBuf;

   SOCKET Socket;

   WSAOVERLAPPED Overlapped;

   DWORD BytesSEND;

   DWORD BytesRECV;

} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

 

int main(int argc, char** argv)

{

            DWORD EventTotal = 0;

            WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];

            LPSOCKET_INFORMATION SocketArray[WSA_MAXIMUM_WAIT_EVENTS];

            CHAR AcceptBuffer[2 * (sizeof(SOCKADDR_IN) + 16)];

            WSAOVERLAPPED ListenOverlapped;

            DWORD Bytes;

            DWORD Index;

            DWORD Flags;

            DWORD BytesTransferred;

            LPSOCKET_INFORMATION SI;

            WSADATA wsaData;

            SOCKET ListenSocket, AcceptSocket;

            SOCKADDR_IN InternetAddr;

            DWORD RecvBytes, SendBytes;

            DWORD i;

 

            if ((WSAStartup((2,2),&wsaData)) != 0)

            {

                        printf("WSAStartup() failed with error %d\n", WSAGetLastError());

                        WSACleanup();

                        return 1;

            }

            else

                        printf("WSAStartup() is OK!\n");

 

            if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)

            {

                        printf("Failed to get a socket %d\n", WSAGetLastError());

                        return 1;

            }

            else

                        printf("WSASocket() is OK!\n");

 

            InternetAddr.sin_family = AF_INET;

            InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);

            InternetAddr.sin_port = htons(PORT);

 

            if (bind(ListenSocket, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)

            {

                        printf("bind() failed with error %d\n", WSAGetLastError());

                        return 1;

            }

            else

                        printf("bind() is OK!\n");

 

            if (listen(ListenSocket, 5))

            {

                        printf("listen() failed with error %d\n", WSAGetLastError());

                        return 1;

            }

            else

                        printf("listen() is OK! I am listening...\n");

 

 

 

 

            // Setup the listening socket for connections

            if ((AcceptSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)

            {

                        printf("Failed to get a socket %d\n", WSAGetLastError());

                        return 1;

            }

            else

                        printf("WSASocket() is OK!\n");

 

            ZeroMemory(&ListenOverlapped, sizeof(OVERLAPPED));

            if ((EventArray[0] = ListenOverlapped.hEvent = WSACreateEvent()) == WSA_INVALID_EVENT)

            {

                        printf("WSACreateEvent() failed with error %d\n", WSAGetLastError());

                        return 1;

            }

            else

                        printf("WSACreateEvent() is OK!\n");

 

            EventTotal = 1;

 

            if (AcceptEx(ListenSocket, AcceptSocket, (PVOID) AcceptBuffer, 0,

                        sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, &Bytes, &ListenOverlapped) == FALSE)

 

                        if (WSAGetLastError() != ERROR_IO_PENDING)

                        {

                                    printf("AcceptEx() failed with error %d\n", WSAGetLastError());

                                    return 1;

                        }

                        else

                                    printf("AcceptEx() is OK!\n");

 

                        // Process asynchronous AcceptEx, WSASend, WSARecv requests

                        while(TRUE)

                        {

                                    if ((Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED)

                                    {

                                                printf("WSAWaitForMultipleEvents() failed %d\n", WSAGetLastError());

                                                return 1;

                                    }

                                    else

                                                printf("WSAWaitForMultipleEvents() is OK!\n");

                                    // If the event triggered was zero then a connection attempt was made

                                    // on our listening socket

                                    if ((Index - WSA_WAIT_EVENT_0) == 0)

                                    {

                                                // Check the returns from the overlapped I/O operation on the listening socket

                                                if (WSAGetOverlappedResult(ListenSocket, &(ListenOverlapped), &BytesTransferred, FALSE, &Flags) == FALSE)

                                                {

                                                            printf("WSAGetOverlappedResult() failed with error %d\n", WSAGetLastError());

                                                            return 1;

                                                }

                                                else

                                                            printf("WSAGetOverlappedResult() is OK!\n");

 

                                                printf("Socket %d got connected...\n", AcceptSocket);

                                                if (EventTotal > WSA_MAXIMUM_WAIT_EVENTS)

                                                {

                                                            printf("Too many connections - closing socket.\n");

                                                            closesocket(AcceptSocket);

                                                            continue;

                                                }

                                                else

                                                {

                                                            // Create a socket information structure to associate with the accepted socket

                                                            if ((SocketArray[EventTotal] = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,

                                                                        sizeof(SOCKET_INFORMATION))) == NULL)

                                                            {

                                                                        printf("GlobalAlloc() failed with error %d\n", GetLastError());

                                                                        return 1;

                                                            }

                                                            else

                                                                        printf("GlobalAlloc() for LPSOCKET_INFORMATION is OK!\n");

 

                                                            // Fill in the details of our accepted socket

                                                            SocketArray[EventTotal]->Socket = AcceptSocket;

                                                            ZeroMemory(&(SocketArray[EventTotal]->Overlapped), sizeof(OVERLAPPED));

                                                            SocketArray[EventTotal]->BytesSEND = 0;

                                                            SocketArray[EventTotal]->BytesRECV = 0;

                                                            SocketArray[EventTotal]->DataBuf.len = DATA_BUFSIZE;

                                                            SocketArray[EventTotal]->DataBuf.buf = SocketArray[EventTotal]->Buffer;

 

                                                            if ((SocketArray[EventTotal]->Overlapped.hEvent = EventArray[EventTotal] = WSACreateEvent())

                                                                        == WSA_INVALID_EVENT)

                                                            {

                                                                        printf("WSACreateEvent() failed with error %d\n", WSAGetLastError());

                                                                        return 1;

                                                            }

                                                            else

                                                                        printf("WSACreateEvent() is OK!\n");

 

                                                            // Post a WSARecv request to to begin receiving data on the socket

                                                            if (WSARecv(SocketArray[EventTotal]->Socket, &(SocketArray[EventTotal]->DataBuf), 1, &RecvBytes, &Flags,

                                                                        &(SocketArray[EventTotal]->Overlapped), NULL) == SOCKET_ERROR)

                                                            {

                                                                        if (WSAGetLastError() != ERROR_IO_PENDING)

                                                                        {

                                                                                    printf("WSARecv() failed with error %d\n", WSAGetLastError());

                                                                                    return 1;

                                                                        }

                                                            }

                                                            else

                                                                        printf("WSARecv() is OK!\n");

 

                                                            EventTotal++;

                                                }

 

                                                // Make a new socket for accepting future connections and post another AcceptEx call

                                                if ((AcceptSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,

                                                            WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)

                                                {

                                                            printf("Failed to get a socket %d\n", WSAGetLastError());

                                                            return 1;

                                                }

                                                else

                                                            printf("WSASocket() is OK!\n");

 

                                                WSAResetEvent(EventArray[0]);

                                                ZeroMemory(&ListenOverlapped, sizeof(OVERLAPPED));

                                                ListenOverlapped.hEvent = EventArray[0];

 

                                                if (AcceptEx(ListenSocket, AcceptSocket, (PVOID) AcceptBuffer, 0,

                                                            sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, &Bytes, &ListenOverlapped) == FALSE)

                                                {

                                                            if (WSAGetLastError() != ERROR_IO_PENDING)

                                                            {

                                                                        printf("AcceptEx() failed with error %d\n", WSAGetLastError());

                                                                        return 1;

                                                            }

                                                }

                                                else

                                                            printf("AcceptEx() is OK!\n");

                                                continue;

                                    }

 

                                    SI = SocketArray[Index - WSA_WAIT_EVENT_0];

                                    WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);

                                    if (WSAGetOverlappedResult(SI->Socket, &(SI->Overlapped), &BytesTransferred, FALSE, &Flags) == FALSE)

                                    {

                                                printf("WSAGetOverlappedResult() failed with error %d\n", WSAGetLastError());

                                                return 1;

                                    }

                                    else

                                                printf("WSAGetOverlappedResult() is OK!\n");

 

                                    // First check to see if the peer has closed the connection and if so

                                    // then close the socket and cleanup the SOCKET_INFORMATION structure

                                    // associated with the socket

                                    if (BytesTransferred == 0)

                                    {

                                                printf("Closing socket %d\n", SI->Socket);

                                                if (closesocket(SI->Socket) == SOCKET_ERROR)

                                                {

                                                            printf("closesocket() failed with error %d\n", WSAGetLastError());

                                                }

                                                else

                                                            printf("closesocket() is OK!\n");

 

                                                GlobalFree(SI);

                                                WSACloseEvent(EventArray[Index - WSA_WAIT_EVENT_0]);

                                                // Cleanup SocketArray and EventArray by removing the socket event handle

                                                // and socket information structure if they are not at the end of the arrays

                                                if ((Index - WSA_WAIT_EVENT_0) + 1 != EventTotal)

                                                            for (i = Index - WSA_WAIT_EVENT_0; i < EventTotal; i++)

                                                            {

                                                                        EventArray[i] = EventArray[i + 1];

                                                                        SocketArray[i] = SocketArray[i + 1];

                                                            }

 

                                                            EventTotal--;

                                                            continue;

                                    }

 

 

 

 

                                    // Check to see if the BytesRECV field equals zero. If this is so, then

                                    // this means a WSARecv call just completed so update the BytesRECV field

                                    // with the BytesTransferred value from the completed WSARecv() call

                                    if (SI->BytesRECV == 0)

                                    {

                                                SI->BytesRECV = BytesTransferred;

                                                SI->BytesSEND = 0;

                                    }

                                    else

                                    {

                                                SI->BytesSEND += BytesTransferred;

                                    }

 

                                    if (SI->BytesRECV > SI->BytesSEND)

                                    {

                                                // Post another WSASend() request

                                                // Since WSASend() is not guaranteed to send all of the bytes requested,

                                                // continue posting WSASend() calls until all received bytes are sent

                                                ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED));

                                                SI->Overlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];

                                                SI->DataBuf.buf = SI->Buffer + SI->BytesSEND;

                                                SI->DataBuf.len = SI->BytesRECV - SI->BytesSEND;

 

                                               if (WSASend(SI->Socket, &(SI->DataBuf), 1, &SendBytes, 0, &(SI->Overlapped), NULL) == SOCKET_ERROR)

                                                {

                                                            if (WSAGetLastError() != ERROR_IO_PENDING)

                                                            {

                                                                        printf("WSASend() failed with error %d\n", WSAGetLastError());

                                                                        return 1;

                                                            }

                                                }

                                                else

                                                            printf("WSASend() is OK!\n");

                                    }

                                    else

                                    {

                                                SI->BytesRECV = 0;

                                                // Now that there are no more bytes to send post another WSARecv() request

                                                Flags = 0;

                                                ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED));

                                                SI->Overlapped.hEvent = EventArray[Index - WSA_WAIT_EVENT_0];

                                                SI->DataBuf.len = DATA_BUFSIZE;

                                                SI->DataBuf.buf = SI->Buffer;

 

                                                if (WSARecv(SI->Socket, &(SI->DataBuf), 1, &RecvBytes, &Flags, &(SI->Overlapped), NULL) == SOCKET_ERROR)

                                                {

                                                            if (WSAGetLastError() != ERROR_IO_PENDING)

                                                            {

                                                                        printf("WSARecv() failed with error %d\n", WSAGetLastError());

                                                                        return 1;

                                                            }

                                                }

                                                else

                                                            printf("WSARecv() is OK!\n");

                                    }

  }

}

 

Build and run the project.

 

-------------------------------------------------------------

The Overlapped IO Model: The overlapped example using AcceptEx() - running the program as receiver/server, waiting for connection

 

Running the Server and Client Programs

 

Firstly we run the server program. The following screenshot shows a sample output.

 

The Overlapped IO Model: The overlapped example using AcceptEx() - running the program as receiver/sender for client connection

 

Then we run the client program.

 

The Overlapped IO Model: The overlapped example using AcceptEx() - running the sender/client program

 

The following screenshot shows a sample server output when some connection were completed.

 

The Overlapped IO Model: The overlapped example using AcceptEx() - the previous receiver/server sample output when communication was completed

 

 

 


< Overlapped Model & Example | Winsock2 I/O Method Main | Overlapped I/O with Callback Example >