Directory Services

Example Code for Implementing a Winsock Service with an RnR Publication

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

This sample uses the serverRegister function defined in the Example Code for Publishing the RnR Connection Point topic and the serverUnregister function defined in the Example Code for Removing the RnR Connection Point topic.

[C++]
#include <winsock2.h>
#include <stdio.h>

// {A9033BC1-ECA4-11cf-A054-00AA006C33ED}
static GUID SVCID_EXAMPLE_SERVICE = 
{ 0xa9033bc1, 0xeca4, 0x11cf, { 0xa0, 0x54, 0x0, 0xaa, 0x0, 0x6c, 0x33, 0xed } };

INT serverRegister(SOCKADDR *sa, 
				 GUID *pServiceID, 
				 LPTSTR pszServiceInstanceName, 
				 LPTSTR pszServiceInstanceComment);
INT serverUnregister(SOCKADDR *sa, 
					 GUID *pServiceID, 
					 LPTSTR pszServiceInstanceName, 
					 LPTSTR pszServiceInstanceComment);

int main(void) 
{
	LPTSTR pszServiceInstanceName = TEXT("Example Service Instance");
	LPTSTR pszServiceInstanceComment = TEXT("ExampleService instance registered in the directory service through RnR");

	// Data structures used to initialize Winsock.
	WSADATA wsData;
	WORD wVer = MAKEWORD(2,2);

	// Data structures used to setup 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 (INVALID_SOCKET == s) 
	{
		printf("Failed to create socket: %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
}

	// Disable non-blocking I/O for 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));

	// 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));
}

	// Identify the net address to fill in to register ourselves
	// in the directory service. Explicitly call the ANSI text version 
	// because gethostbyname does not recognize Unicode.

	ilen = sizeof(szName);
	GetComputerNameA(szName,&ulLen);
	he = gethostbyname(szName);

	// Put the address in the SOCKADDR structure.
	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, 
		&SVCID_EXAMPLE_SERVICE, 
		pszServiceInstanceName, 
		pszServiceInstanceComment);
	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. For simplicity, this example
	// is single-threaded. 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());
}
	else
	{
		printf("Server: There is a client connection\n");

		// Receive a message from the client and end.
		status = recv(newsock,(char *)wszRecvBuf,sizeof(wszRecvBuf),0);
		if (status > 0)
		{
			printf("Server: Received: %S\n",wszRecvBuf);
	}
}

	// Unregister and end.
	printf("Unregistering and shutting down.\n");
	status = serverUnregister((SOCKADDR *)&sa_in, 
		&SVCID_EXAMPLE_SERVICE, 
		pszServiceInstanceName, 
		pszServiceInstanceComment);

	WSACleanup();

	return 0;
}