Platform SDK: Active Directory, ADSI, and Directory Services

Example Code for Implementing a Winsock Service with an RnR Publication

The following program implements the example Winsock service with RnR publication.

This sample calls the serverRegister and serverUnregister sample routines, which are documented in the Example Code for Publishing the RnR Connection Point section.

/*
** Simple Winsock Server
*/
#include <winsock2.h>
#include <stdio.h>
 
 
INT serverRegister(SOCKADDR *);
INT serverUnregister(SOCKADDR *);
 
HRESULT
main(void) 
{
 
 
    //Data structures for initializing Winsock.
 
    WSADATA wsData;
    WORD    wVer = MAKEWORD(2,2);
 
 
    //Data structures for setting up communications.
 
    SOCKET        s, newsock;
    SOCKADDR    sa;
    struct hostent    *he;
    char    szName[255];
    
    struct sockaddr_in sa_in;
 
    INT            ilen;
    ULONG        icmd;
    ULONG        ulLen;
 
    //Miscellaneous variables
 
    INT status;
    WCHAR    wszRecvBuf[100];
 
    memset(wszRecvBuf,0,sizeof(wszRecvBuf));
 
    //Begin: Init Winsock2
 
 
    status = WSAStartup(wVer,&wsData);
    if (status != NO_ERROR)
        return -1;
 
    //Create the socket.
 
    s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if (s == INVALID_SOCKET) {
        printf("Failed to create socket: %d\n",WSAGetLastError());
        WSACleanup();
        return -1;
    }
 
 
    //Disable non-blocking IO for purposes of this example.
 
    icmd = 0;   
    status = ioctlsocket(s,FIONBIO,&icmd);
 
 
    //Bind the socket to a dynamically assigned port.
 
    sa.sa_family=AF_INET;
    memset(sa.sa_data,0,sizeof(sa.sa_data));
 
    status = bind(s,&sa,sizeof(sa));
 
    //Note that we need to convert the port to the local 
    //host byte order.
 
    ilen = sizeof(sa_in);
    status = getsockname(s,(struct sockaddr *)&sa_in,&ilen);
    if (status == NO_ERROR) {
        printf("Server: Bound to port %d\n",ntohs(sa_in.sin_port));
    }
    //Figure out our net address to fill in for registering ourselves
    //in the directory service. Explicitly call the ANSI text version 
    //because gethostbyname does not understand UNICODE.
 
    ilen = sizeof(szName);
    GetComputerNameA(szName,&ulLen);
    he = gethostbyname(szName);
 
    //Put the address in the SOCKADDR struct. This is not
    //as difficult as it looks.

    sa_in.sin_addr.S_un.S_addr = *((long *)(he->h_addr));
 
    //Listen for connections. SOMAXCONN tells the provider to queue
    //a "reasonable" number of connections.

    status = listen(s,SOMAXCONN);
    if (status != NO_ERROR) {
        printf("Failed to set socket listening: %d\n",
                WSAGetLastError());
        WSACleanup();
        return -1;
    }
 
    //Register this instance with RnR.
 
    status = serverRegister((SOCKADDR *)&sa_in);
    if (status != NO_ERROR) {
        printf("Failed to register instance: %d\n",WSAGetLastError());
        WSACleanup();
        return -1;
    }
    printf("Server: Registered instance in the directory service\n");
 
    //Block waiting for a connection. This example is single-threaded
    //for simplicity. In a real service, spin off 
    //one or more threads here to call AcceptEx here and process the
    //connections through a completion port.  
 
    ilen = sizeof(sa);
    newsock = accept(s,&sa,&ilen);
    if (newsock == INVALID_SOCKET) 
    {
        printf("Failed to create socket: %d\n",WSAGetLastError());
        status = serverUnregister((SOCKADDR *)&sa_in);
        WSACleanup();
        return -1;
    }
    
    printf("Server: There is a client connection\n");
 
    //Receive a message from the client and shut down.
 
    status = recv(newsock,(char *)wszRecvBuf,sizeof(wszRecvBuf),0);
    if (status > 0)
            printf("Server: Received: %S\n",wszRecvBuf);
 
    //Unregister ourselves
    printf("Unregistering and shutting down.\n");
    status = serverUnregister((SOCKADDR *)&sa_in);
 
    WSACleanup();
    return 0;
}