Share via


IPv6-Enabled Client Code (Windows Embedded CE 6.0)

1/6/2010

The following code is the IP independent CeClientApp.cpp file. This is an IPv6-enabled version of the CeClientApp.cpp file found in IPv4-only Client Code.

#include <winsock2.h>
#include <ws2tcpip.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

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 nFamily = DEFAULT_FAMILY;
   int nSockType = DEFAULT_SOCKTYPE;
   char szRemoteName[64];
   char *szPort = DEFAULT_PORT;
   SOCKADDR_STORAGE ssRemoteAddr;
   int cbXfer, cbTotalRecvd, cbRemoteAddrSize;
   WSADATA wsaData;
   ADDRINFO Hints, *AddrInfo = NULL, *AI;
   char szRemoteAddrString[RAS_SIZE];
   fd_set fdReadSet;
   TIMEVAL timeout = {TIMEOUT_SECS, TIMEOUT_USECS};
   char pRecvBuf[BUFFER_SIZE];

   if(WSAStartup(MAKEWORD(2,2), &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
   //

   memset(&Hints, 0, sizeof(Hints));
   Hints.ai_family = nFamily;
   Hints.ai_socktype = nSockType;

   if(getaddrinfo(szRemoteName, szPort, &Hints, &AddrInfo))
   {
      Print(TEXT("ERROR: Couldn't get resolve the server name/address!"));
      goto Cleanup;
   }

   //
   // Attempt to connect to each address until we find one that succeeds
   //

   for(AI = AddrInfo; AI != NULL; AI = AI->ai_next) 
   {
      if((AI->ai_family == PF_INET) || (AI->ai_family == PF_INET6)) // only want PF_INET or PF_INET6
      {
         sock = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
         if (sock != INVALID_SOCKET)
         {
            if (AI->ai_socktype == SOCK_STREAM)
            {
               if(connect(sock, AI->ai_addr, AI->ai_addrlen) == SOCKET_ERROR)
               {
                  // Connect failed, let's close this socket and try again on the next address in the list
                  closesocket(sock);
                  continue;
               }
            }

            // connect() succeeded or we're a UDP socket
            break;
         }
      }
   }
   
   if (AI == NULL) 
   {
      Print(TEXT("ERROR: Unable to connect to any of the server's addresses!\r\n"));
      goto Cleanup;
   }

   //
   // Send data to the server
   //

   cbXfer = 0;
   cbXfer = sendto(sock, pBuf, sizeof(pBuf), 0, AI->ai_addr, AI->ai_addrlen);

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

   if (getnameinfo(AI->ai_addr, AI->ai_addrlen,
      szRemoteAddrString, sizeof(szRemoteAddrString), NULL, 0, NI_NUMERICHOST) != 0)
      strcpy(szRemoteAddrString, "");
   
   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(ssRemoteAddr);
      cbXfer = recvfrom(sock, pRecvBuf + cbTotalRecvd, sizeof(pRecvBuf) - cbTotalRecvd, 0, 
         (SOCKADDR *)&ssRemoteAddr, &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(&ssRemoteAddr, 0, sizeof(ssRemoteAddr));
      cbRemoteAddrSize = sizeof(ssRemoteAddr);
      getpeername(sock, (SOCKADDR *)&ssRemoteAddr, &cbRemoteAddrSize);
   }

   if (getnameinfo((SOCKADDR *)&ssRemoteAddr, cbRemoteAddrSize,
      szRemoteAddrString, sizeof(szRemoteAddrString), NULL, 0, NI_NUMERICHOST) != 0)
      strcpy(szRemoteAddrString, "");

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

Cleanup:

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

   if(AddrInfo)
      freeaddrinfo(AddrInfo);

   WSACleanup();

   return 0;
}

See Also

Concepts

IPv4-only Client Code

Other Resources

IP Independent Source Code Examples