Partager via


Socket Client (Windows Embedded CE 6.0)

1/6/2010

The following code sample shows how to implement a Winsock client. It sends data to the server and gets the echoed data back from the server. This sample can be run on the same device with the Socket Server application. In this case, use "localhost" as the application's parameter. Otherwise, use a full server name or address.

#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

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

    va_start (ArgList, pFormat);

   (void)StringCchPrintf(Buffer, 256, pFormat, ArgList);
#ifndef UNDER_CE
    _putts(Buffer);
#else
    printf("%s",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[128];
    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

Tasks

Creating a Socket Client Application

Concepts

Stream Socket Application
Creating a Socket Server Application
Socket Server