Share via


IPv4-only Client Code (Windows Embedded CE 6.0)

1/6/2010

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

#include <winsock.h>
#include <windows.h>
#include <tchar.h>
#include <strsafe.h.>
char pBuf[] = "WinCE Echo Test Packet";

#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 TIMEOUT_SECS      2
#define TIMEOUT_USECS      0

#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 = INVALID_SOCKET;
   int nSockType = DEFAULT_SOCKTYPE;
   char szRemoteName[64];
   short sPort = DEFAULT_PORT;
   sockaddr_in saRemoteAddr;
   int cbXfer, cbTotalRecvd, cbRemoteAddrSize;
   WSADATA wsaData;
   DWORD dwIPAddr;
   struct hostent* h;
   char szRemoteAddrString[RAS_SIZE];
   fd_set fdReadSet;
   TIMEVAL timeout = {TIMEOUT_SECS, TIMEOUT_USECS};
   char pRecvBuf[BUFFER_SIZE];

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

   if(argc < 2)
   {
      Print(TEXT("Server name/address parameter required.  Ex: clnt 123.45.67.89"));
      goto Cleanup;
   }
   else
   {
      // we use the first argument as the server name/address
#if defined UNICODE
      wcstombs(szRemoteName, argv[1], sizeof(szRemoteName));
#else
      strncpy(szRemoteName, argv[1], sizeof(szRemoteName));
#endif
szRemoteName[63] = _T('\0');
      Print(TEXT("Communicating with server - %hs\r\n"), szRemoteName);
   }

   //
   // Resolve the server name/address
   //

   if ((dwIPAddr = inet_addr(szRemoteName)) == INADDR_NONE)
   {
      // remote server is not a dotted decimal IP address
      h = gethostbyname(szRemoteName);
      if(h != NULL)
      {
         memcpy(&dwIPAddr, h->h_addr_list[0], sizeof(dwIPAddr) );
      }
      else
      {
         Print (TEXT("Invalid address parameter = %s"), szRemoteName);
         goto Cleanup;
      }
   }
   
   sock = socket(AF_INET, nSockType, 0);

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

   saRemoteAddr.sin_family = AF_INET;
   saRemoteAddr.sin_addr.s_addr = dwIPAddr;
   saRemoteAddr.sin_port = htons(sPort);

   if(nSockType == SOCK_STREAM)
   {
      // connect
      if(connect(sock, (sockaddr *)&saRemoteAddr, sizeof(saRemoteAddr)) == SOCKET_ERROR)
      {
         Print(TEXT("connect() failed with error %d"), WSAGetLastError());
         goto Cleanup;
      }
      else
         Print(TEXT("connect()'d successfully to 0x%08x"), dwIPAddr);
   }
   
   //
   // Send data to the server
   //

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

   if(cbXfer != sizeof(pBuf))
   {
      Print(TEXT("ERROR: Couldn't send the data! error = %d\r\n"), WSAGetLastError());
      goto Cleanup;
   }

   h = gethostbyaddr((char *)&dwIPAddr, sizeof(dwIPAddr), 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"), dwIPAddr);
      strcpy(szRemoteAddrString, inet_ntoa(*((in_addr*)&dwIPAddr)));
   }
   
   Print(TEXT("SUCCESS - Sent %d bytes to address %hs\r\n"), cbXfer, szRemoteAddrString);

   //
   // Receive the echo'd data back from the server
   //

   FD_ZERO(&fdReadSet);
   FD_SET(sock, &fdReadSet);

   if(select(0, &fdReadSet, NULL, NULL, &timeout) != 1)
   {
      Print(TEXT("ERROR: Server hasn't responded in %d milliseconds\r\n"), 
         ((timeout.tv_sec * 1000) + (timeout.tv_sec / 1000)));
      goto Cleanup;
   }

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

   if(cbXfer == SOCKET_ERROR)
   {
      Print(TEXT("ERROR: Couldn't receive the data! Error = %d\r\n"), WSAGetLastError());
      goto Cleanup;
   }
   else if(cbTotalRecvd != sizeof(pRecvBuf))
   {
      Print(TEXT("ERROR: Server didn't send back all the expected data!\r\n"));
      goto Cleanup;
   }

   if(nSockType == SOCK_STREAM)
   {
      memset(&saRemoteAddr, 0, sizeof(saRemoteAddr));
      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 back from address %hs\r\n"), cbTotalRecvd, szRemoteAddrString);

Cleanup:

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

   WSACleanup();

   return 0;
}

See Also

Concepts

IPv6-Enabled Client Code

Other Resources

IPv4-only Source Code Examples