IPv4-only Server Code (Windows Embedded CE 6.0)

1/6/2010

The following code is the CeServerApp.cpp file. This is an IPv4-only Windows Sockets server. Use this code for comparison purposes only. For an example of how to write an IPv6-enabled server, see IPv6-Enabled Server Code.

#include <winsock.h>
#include <windows.h>
#include <tchar.h>
#include <strsafe.h.>

#define DEFAULT_FAMILY      AF_UNSPEC
#define DEFAULT_SOCKTYPE   SOCK_STREAM
#define DEFAULT_PORT      1234
#define BUFFER_SIZE         23            // length of "WinCE Echo Test Packet"

#define RAS_SIZE 128

#define MIN(a,b) ((a) <= (b)) ? (a) : (b)

void
Print(
   TCHAR *pFormat, 
   ...)
{
   va_list ArgList;
   TCHAR   Buffer[256];

   va_start (ArgList, pFormat);

   (void)StringCchVPrintf(Buffer, 256, pFormat, ArgList);

#ifndef UNDER_CE
   _putts(Buffer);
#else
   OutputDebugString(Buffer);
#endif

   va_end(ArgList);
}

int _tmain (int argc, TCHAR* argv[])
{
   SOCKET sock, SockServ;
   int nSockType = DEFAULT_SOCKTYPE;
   short sPort = DEFAULT_PORT;
   sockaddr_in saAddr, saRemoteAddr;
   int cbRemoteAddrSize, cbXfer, cbTotalRecvd;
   WSADATA wsaData;
   struct hostent* h;
   fd_set fdSockSet;
   char pBuf[BUFFER_SIZE];
   char szRemoteAddrString[RAS_SIZE];

   if(WSAStartup(MAKEWORD(1,1), &wsaData))
   {
      // WSAStartup failed
      return 1;
   }

   sock = INVALID_SOCKET;
   SockServ = INVALID_SOCKET;
   
   //
   // Create socket
   //

   SockServ = socket(AF_INET, nSockType, 0);

   if(SockServ == INVALID_SOCKET)
   {
      Print(TEXT("socket() failed with error %d"), WSAGetLastError());
      goto Cleanup;
   }

   //
   // bind the socket
   //

   saAddr.sin_family = AF_INET;
   saAddr.sin_addr.s_addr = INADDR_ANY;
   saAddr.sin_port = htons(sPort);

   if(bind(SockServ, (SOCKADDR *)&saAddr, sizeof(saAddr)) == SOCKET_ERROR)
   {
      Print(TEXT("bind() failed with error %d"), WSAGetLastError());
      goto Cleanup;
   }

   if(nSockType == SOCK_STREAM)
   {
      // listen
      if(listen(SockServ, 5) == SOCKET_ERROR)
      {
         Print(TEXT("listen() failed with error %d"), WSAGetLastError());
         goto Cleanup;
      }
   }

   //
   // Wait for incomming data/connections
   //

   FD_ZERO(&fdSockSet);
   FD_SET(SockServ, &fdSockSet);

   if (select(1, &fdSockSet, 0, 0, NULL) == SOCKET_ERROR)
   {
      Print(TEXT("ERROR: select() failed with error = %d\r\n"), WSAGetLastError());
      goto Cleanup;
   }

   if (FD_ISSET(SockServ, &fdSockSet))   // proceed for connected socket
   {
      FD_CLR(SockServ, &fdSockSet);
      if(nSockType == SOCK_STREAM)
      {
         cbRemoteAddrSize = sizeof(saRemoteAddr);
         sock = accept(SockServ, (SOCKADDR*)&saRemoteAddr, &cbRemoteAddrSize);
         if(sock == INVALID_SOCKET) 
         {
            Print(TEXT("ERROR: accept() failed with error = %d\r\n"), WSAGetLastError());
            goto Cleanup;
         }

         Print(TEXT("Accepted TCP connection from socket 0x%08x\r\n"), sock);
      }
      else
      {
         sock = SockServ;
         Print(TEXT("UDP data available on socket 0x%08x\r\n"), sock);
      }
   }
   else
   {
      Print(TEXT("ERROR: select returned success but FD_ISSET returns false for socket = 0x%08x\r\n"), SockServ);
      goto Cleanup;
   }

   //
   // Receive data from a client
   //

   cbTotalRecvd = 0;
   do
   {
      cbRemoteAddrSize = sizeof(saRemoteAddr);
      cbXfer = recvfrom(sock, pBuf + cbTotalRecvd, sizeof(pBuf) - cbTotalRecvd, 0,
         (sockaddr *)&saRemoteAddr, &cbRemoteAddrSize);
      cbTotalRecvd += cbXfer;
   } while(cbXfer > 0 && cbTotalRecvd < sizeof(pBuf));

   if(cbXfer == SOCKET_ERROR)
   {
      Print(TEXT("ERROR: Couldn't receive the data! Error = %d\r\n"), WSAGetLastError());
      goto Cleanup;
   }
   else if(cbXfer == 0)
   {
      Print(TEXT("ERROR: Didn't get all the expected data from the client!\r\n"));
      goto Cleanup;
   }

   if(nSockType == SOCK_STREAM)
   {
      cbRemoteAddrSize = sizeof(saRemoteAddr);
      getpeername(sock, (SOCKADDR *)&saRemoteAddr, &cbRemoteAddrSize);
   }
   
   h = gethostbyaddr((char *)&(saRemoteAddr.sin_addr.s_addr), sizeof(saRemoteAddr.sin_addr.s_addr), AF_INET);
   if(h != NULL)
   {
      memcpy(szRemoteAddrString, h->h_name, MIN(strlen(h->h_name)+1, RAS_SIZE-1));
      szRemoteAddrString[RAS_SIZE-1] = _T('\0');      
   }
   else
   {
      Print (TEXT("Invalid address parameter = 0x%08x"), saRemoteAddr.sin_addr.s_addr);
      strcpy(szRemoteAddrString, inet_ntoa(*((in_addr*)&(saRemoteAddr.sin_addr.s_addr))));
   }

   Print(TEXT("SUCCESS - Received %d bytes from client %hs\r\n"), cbTotalRecvd, szRemoteAddrString);

   //
   // Echo the data back to the client
   //

   cbXfer = 0;
   cbXfer = sendto(sock, pBuf, cbTotalRecvd, 0, (sockaddr *)&saRemoteAddr, cbRemoteAddrSize);

   if(cbXfer != cbTotalRecvd)
      Print(TEXT("ERROR: Couldn't send the data! error = %d\r\n"), WSAGetLastError());
   else
      Print(TEXT("SUCCESS - Echo'd %d bytes back to the client\r\n"), cbXfer);

Cleanup:

   if (SockServ != INVALID_SOCKET)
      closesocket(SockServ);

   if(sock != INVALID_SOCKET)
   {
      shutdown(sock, 2);
      closesocket(sock);
   }

   WSACleanup();

   return 0;
}

See Also

Concepts

IPv6-Enabled Server Code

Other Resources

IPv4-only Source Code Examples