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.
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.
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.
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.
12. If there is no error, the following output should be expected.
Now that you understand how to construct a server that can receive a client connection, we will describe how to construct a client.