An Intro to Windows Socket (Winsock2) Programming 8

 

 

 

 

 

Server Program Example

 

The following program example demonstrates how to write a simple server that can accept one TCP/IP connection. We did not perform full error checking on the calls to make reading the code less confusing.

 

1.   Click File menu > Project sub menu to create a new project. Select Win32 for the Project types: and Win32 Console Application for the Templates:. Put the project and solution name. Adjust the project location if needed and click OK.

 

Windows Socket (Winsock2) Programming and  C Language: creating a new Win32 console application project

 

2.   Click Next for the Win32 Application Wizard Overview page. We will remove all the unnecessary project items. In the Application page, select Empty project for the Additional options:. Leave others as given and click Finish.

 

Windows Socket (Winsock2) Programming and  C Language: selecting an empty console application

 

3.   Next, we need to add new source file. Click Project menu > Add New Item sub menu or select the project folder in the Solution Explorer > Select Add menu > Select New Item sub menu.

4.   Select C++ File (.cpp) for the Templates:. Put the source file name and click Add. Although the extension is .cpp, Visual C++ IDE will recognize that the source code used is C based on the Compile as C Code (/TC) option which will be set in the project property page later.

 

Windows Socket (Winsock2) Programming and  C Language: adding C++ source file to the existing Visual C++ project

 

5.   Now, add the source code as given below.

 

#include <winsock2.h>

#include <stdio.h>

 

int main(void)

{

            WSADATA                            wsaData;

            SOCKET                                ListeningSocket;

            SOCKET                                NewConnection;

            SOCKADDR_IN                   ServerAddr;

            int                                            Port = 5150;

           

            // Initialize Winsock version 2.2

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

            {

                        // MSDN: An application can call the WSAGetLastError() function to determine the

                        // extended error code for other Windows sockets functions as is normally

                        // done in Windows Sockets even if the WSAStartup function fails or the WSAStartup

                        // function was not called to properly initialize Windows Sockets before calling a

                        // Windows Sockets function. The WSAGetLastError() function is one of the only functions

                        // in the Winsock 2.2 DLL that can be called in the case of a WSAStartup failure

                        printf("Server: WSAStartup failed with error %ld\n", WSAGetLastError());

                        // Exit with error

                        return -1;

            }

            else

            {

                        printf("Server: The Winsock dll found!\n");

                        printf("Server: The current status is %s.\n", wsaData.szSystemStatus);

            }

           

            if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 )

            {

                        // Tell the user that we could not find a usable WinSock DLL

                        printf("Server: The dll do not support the Winsock version %u.%u!\n", LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion));

                        // Do the clean up

                        WSACleanup();

                        // and exit with error

                        return -1;

            }

            else

            {

                        printf("Server: The dll supports the Winsock version %u.%u!\n", LOBYTE(wsaData.wVersion),HIBYTE(wsaData.wVersion));

                        printf("Server: The highest version this dll can support is %u.%u\n", LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));

            }

           

            // Create a new socket to listen for client connections.

            ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

           

            // Check for errors to ensure that the socket is a valid socket.

            if (ListeningSocket == INVALID_SOCKET)

            {

                        printf("Server: Error at socket(), error code: %ld\n", WSAGetLastError());

                        // Clean up

                        WSACleanup();

                        // and exit with error

                        return -1;

            }

            else

                        printf("Server: socket() is OK!\n");

           

            // Set up a SOCKADDR_IN structure that will tell bind that we

            // want to listen for connections on all interfaces using port 5150.

 

            // The IPv4 family

            ServerAddr.sin_family = AF_INET;

            // host-to-network byte order

            ServerAddr.sin_port = htons(Port);

            // Listen on all interface, host-to-network byte order

            ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);

           

            // Associate the address information with the socket using bind.

            // Call the bind function, passing the created socket and the sockaddr_in

            // structure as parameters. Check for general errors.

            if (bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)

            {

                        printf("Server: bind() failed! Error code: %ld.\n", WSAGetLastError());

                        // Clos the socket

                        closesocket(ListeningSocket);

                        // Do the clean up

                        WSACleanup();

                        // and exit with error

                        return -1;

            }

            else

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

           

            // Listen for client connections. We used a backlog of 5, which

            // is normal for many applications.

            if (listen(ListeningSocket, 5) == SOCKET_ERROR)

            {

                        printf("Server: listen(): Error listening on socket %ld.\n", WSAGetLastError());

                        // Close the socket

                        closesocket(ListeningSocket);

                        // Do the clean up

                        WSACleanup();

                        // Exit with error

                        return -1;

            }

            else

                        printf("Server: listen() is OK, I'm waiting for connections...\n");

           

            printf("Server: accept() is ready...\n");

            // Accept a new connection when one arrives.

            while(1)

            {

                        NewConnection = SOCKET_ERROR;

                        while(NewConnection == SOCKET_ERROR)

                        {

                                    NewConnection = accept(ListeningSocket, NULL, NULL);

                        }

                       

                        printf("Server: accept() is OK...\n");

                        printf("Server: Client connected, ready for receiving and sending data...\n");

                        // Transfer the connected socket to the listening socket

                        ListeningSocket = NewConnection;

                        break;

            }

           

            // At this point you can do two things with these sockets. Wait

            // for more connections by calling accept again on ListeningSocket

            // and start sending or receiving data on NewConnection (need a loop). We will

            // describe how to send and receive data later in the chapter.

           

            // When you are finished sending and receiving data on the

            // NewConnection socket and are finished accepting new connections

            // on ListeningSocket, you should close the sockets using the closesocket API.

            if(closesocket(NewConnection) != 0)

                        printf("Server: Cannot close \"NewConnection\" socket. Error code: %ld\n", WSAGetLastError());

            else

                        printf("Server: Closing \"NewConnection\" socket...\n");

           

            // When your application is finished handling the connections,  call WSACleanup.

            if(WSACleanup() != 0)

                        printf("Server: WSACleanup() failed! Error code: %ld\n", WSAGetLastError());

            else

                        printf("Server: WSACleanup() is OK...\n");

            return 0;

}

 

6.   Before we can build this Winsock C Win32 console application project, we need to set the project to be compiled as C code and link to ws2_32.lib, the Winsock2 library. Invoke the project property page.

7.   Expand the Configuration folder > Expand the C/C++ sub folder. Select the Advanced link and for the Compile As option, select Compile as C Code (/TC).

8.   Next, expand the Linker folder and select the Input link. For the Additional Dependencies option, click the ellipses at the end of the empty field on the right side.

9.   Manually, type the library name, ws2_32.lib and click OK. Or you can just directly type the library name in the empty field on the right of the Additional Dependencies. Click OK. Or you can use the #pragma comment() directive as shown below in the source code

 

#pragma comment(lib, "ws2_32.lib")

 

If the previous steps not done, you will see the following error during the program compilation.

 

1>------ Build started: Project: TCPServer, Configuration: Debug Win32 ------

1>Compiling...

1>TCPServersrc.cpp

1>Compiling manifest to resources...

1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1

1>Copyright (C) Microsoft Corporation.  All rights reserved.

1>Linking...

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__select@20 referenced in function "int __cdecl recvTimeOutTCP(unsigned int,long,long)" (?recvTimeOutTCP@@YAHIJJ@Z)

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__shutdown@8 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__getpeername@12 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__inet_ntoa@4 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__getsockname@12 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__recv@16 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__accept@12 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__listen@8 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__closesocket@4 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__bind@12 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__htonl@4 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__htons@4 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__socket@12 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__WSACleanup@0 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__WSAGetLastError@0 referenced in function _main

1>TCPServersrc.obj : error LNK2019: unresolved external symbol __imp__WSAStartup@8 referenced in function _main

1>C:\Mywinsockproject\TCPServer\Debug\TCPServer.exe : fatal error LNK1120: 16 unresolved externals

1>Build log was saved at "file://c:\Mywinsockproject\TCPServer\TCPServer\Debug\BuildLog.htm"

1>TCPServer - 17 error(s), 0 warning(s)

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

 

10.  Build the project and make sure there is no error which can be seen (if any) in the Output window which  normally docked at the bottom of the IDE by default.

11.  Run the project. Unblock the Windows firewall if any.

 

Windows Socket (Winsock2) Programming and  C Language: unblocking the Windows firewall alert message box

 

12.  If there is no error, the following output should be expected.

 

Windows Socket (Winsock2) Programming and  C Language: a sample Winsock2 server/receiver console application output which is ready to accept connection

 

Now that you understand how to construct a server that can receive a client connection, we will describe how to construct a client.

 

 

 

 

< Winsock2 7 | Windows Socket 2 (Winssock2) | Win32 Programming | Winsock2 9 >