?? rnrcs.c
字號:
// Module: rnrcs.c
//
// Description:
// This sample illustrates how a server can create a socket and
// advertise the existance of the service to clients. It also
// shows how a client with knowledge of the server's name only
// can find out how to connect to the server in order to transmit
// data. The server accomplishes this by installing a service
// class which describes the basic characteristics of the service
// and then registering an instance of the server which references
// the given class. The service can be registered for multiple
// name spaces such as IPX and NTDS.
//
// The client can query the available name spaces for knowledge
// of a service of the given name. If the query completes
// successfully, the address of the service is returned. All
// the client needs to do is use that address in either a
// connect or sendto call.
//
// Compile:
// cl rnrcs.c ws2_32.lib user32.lib ole32.lib
//
// Command Line Arguments/Parameters
// rnrcs -c:ServiceName -s:ServiceName -t:ID -n:NameSpace
// -c:ServiceName Act as client and query for this service name
// -s:ServiceName Act as server and register service as this name
// -t:ID SAP ID to register under
// -n:NameSpace Name space to register service under
// Supported namespaces are NS_ALL, NS_SAP, NS_NTDS
// -d Delete the service if found
//
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <nspapi.h>
#include <svcguid.h>
#include "mynsp.h"
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUM_CSADDRS 20
#define MAX_INTERFACE_LIST 20
#define MAX_NUM_SOCKETS 20
#define MAX_BUFFER_SZ 512
#define MAX_SERVER_NAME_SZ 64
#define DEFAULT_SERVER_NAME "JunkServer"
char szServerName[MAX_SERVER_NAME_SZ]; // Server name
BOOL bServer, // Client or server?
bDeleteService;
DWORD dwUniqueId; // Used to create a GUID
SOCKET sock;
//
// Function: usage
//
// Description:
// Print usage information.
//
void usage(char *progname)
{
printf("usage: %s -c:Service -s -t:ID\n",
progname);
printf(" -c:ServiceName Act as client and query for this service name\n");
printf(" -s:ServiceName Act as server and register service as this name\n");
printf(" -t:ID Unique ID to register under\n");
printf(" -d Delete the service on a successful query\n");
ExitProcess(-1);
}
//
// Function: ValidateArgs
//
// Description:
// Parse command line parameters and set some global variables used
// by the application.
//
void ValidateArgs(int argc, char **argv)
{
int i;
// Set some default values
//
lstrcpy(szServerName, TEXT(DEFAULT_SERVER_NAME));
dwUniqueId = 200;
bDeleteService = FALSE;
for (i=1; i < argc ;i++)
{
if ((argv[i][0] == '-') || (argv[i][0] == '/'))
{
switch (tolower(argv[i][1]))
{
case 't': // SAP id used to generate GUID
//if (lstrlen(argv[i]) > 3)
// dwUniqueId = atoi(&argv[i][3]);
break;
case 'c': // Client, query for given service
bServer = FALSE;
if (lstrlen(argv[i]) > 3)
lstrcpy(szServerName, &argv[i][3]);
break;
case 's': // Server, register as the given service
bServer = TRUE;
if (lstrlen(argv[i]) > 3)
lstrcpy(szServerName, &argv[i][3]);
break;
case 'd':
bDeleteService = TRUE;
break;
default:
usage(argv[0]);
return;
}
}
else
usage(argv[0]);
}
return;
}
//
// Function: EnumNameSpaceProviders
//
// Description:
// Returns an array of those name spaces which our application
// supports. If one day, NS_DNS becomes dynamic, modify this
// function to return that structure as well.
//
WSANAMESPACE_INFO *EnumNameSpaceProviders(int *count)
{
WSANAMESPACE_INFO *nsinfo,
*nsinfocpy;
BYTE *pbuf=NULL,
*pbufcpy=NULL;
DWORD dwBytes;
int i, j,
ret;
*count = 0;
dwBytes = 0;
//
// First find out how big of a buffer we need
//
ret = WSAEnumNameSpaceProviders(&dwBytes, NULL);
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEFAULT)
{
printf("WSAEnumNameSpaceProviders() failed: %d\n",
WSAGetLastError());
return NULL;
}
}
// Allocate this buffer and call the function again
//
pbuf = (BYTE *)GlobalAlloc(GPTR, dwBytes);
if (!pbuf)
{
printf("GlobaAlloc() failed: %d\n", GetLastError());
return NULL;
}
nsinfo = (WSANAMESPACE_INFO *)pbuf;
ret = WSAEnumNameSpaceProviders(&dwBytes, nsinfo);
if (ret == SOCKET_ERROR)
{
printf("WSAEnumNameSpaceProviders() failed: %d\n",
WSAGetLastError());
HeapFree(GetProcessHeap(), 0, pbuf);
return NULL;
}
// Make a copy buffer which we will return our data in
//
pbufcpy = GlobalAlloc(GPTR, dwBytes);
if (!pbufcpy)
{
printf("GlobaAlloc() failed: %d\n", GetLastError());
return NULL;
}
// Loop throug the returned name space structures picking
// those which our app supports
//
nsinfocpy = (WSANAMESPACE_INFO *)pbufcpy;
printf("%d name spaces are available\n", ret);
j = 0;
for(i=0; i < ret ;i++)
{
switch (nsinfo[i].dwNameSpace)
{
// In this example all we want is our own name space
//
case NS_MYNSP:
printf("Found a match: %S\n", nsinfo[i].lpszIdentifier);
memcpy(&nsinfocpy[j++], &nsinfo[i], sizeof(WSANAMESPACE_INFO));
break;
default:
break;
}
}
// Free the original buffer and return our copy of useable name spaces
//
GlobalFree(pbuf);
printf("Found %d useable name spaces\n\n", j);
*count = j;
return nsinfocpy;
}
//
// Function: InstallServiceClass
//
// Description:
// This function installs the service class which is required before
// registering an instance of a service. A service class defines the
// generic attributes of a class of services such as whether it is
// connection oriented or not as well as what protocols is supports
// (IPX, IP, etc).
//
BOOL InstallServiceClass(GUID *svcguid, WSANAMESPACE_INFO *nsinfo, int nscount)
{
WSASERVICECLASSINFO sci;
WSANSCLASSINFO *nsclass=NULL;
DWORD dwOne=1;
TCHAR szServiceClassName[64];
int i,
ret;
BOOL bRet;
bRet = TRUE;
//
// Generate a name of our service class
//
wsprintf(szServiceClassName, TEXT("Service Class/TCP Port: %003d"), dwUniqueId);
printf("Installing service class: '%s'\n", szServiceClassName);
//
// There are 2 attributes we need to set for every name space
// we want to register in: Connection Oriented/Connectionless as
// well as the address family of the protocols we support.
//
nsclass = GlobalAlloc(GPTR, sizeof(WSANSCLASSINFO) * nscount * 2);
if (!nsclass)
{
printf("GlobalAlloc() failed: %d\n", GetLastError());
return FALSE;
}
// Initialize the structure
//
memset(&sci, 0, sizeof(sci));
sci.lpServiceClassId = svcguid;
sci.lpszServiceClassName = szServiceClassName;
sci.dwCount = nscount * 2;
sci.lpClassInfos = nsclass;
printf("Namespace count: %d, Namespace: %d\n", nscount, nsinfo[0].dwNameSpace);
for(i=0; i < nscount ;i++)
{
// No matter what name space we use we set the connection
// oriented attribute to false (i.e. connectionless)
//
nsclass[i*2].lpszName = SERVICE_TYPE_VALUE_CONN;
nsclass[i*2].dwNameSpace = nsinfo[i].dwNameSpace;
nsclass[i*2].dwValueType = REG_DWORD;
nsclass[i*2].dwValueSize = sizeof(DWORD);
nsclass[i*2].lpValue = &dwOne;
if (nsinfo[i].dwNameSpace == NS_MYNSP)
{
// If NS_MYNSP is available we will be running a UDP
// based service on the given port number
//
printf("Setting NS_MYNSP info...\n");
nsclass[(i*2)+1].lpszName = SERVICE_TYPE_VALUE_TCPPORT;
nsclass[(i*2)+1].dwNameSpace = nsinfo[i].dwNameSpace;
nsclass[(i*2)+1].dwValueType = REG_DWORD;
nsclass[(i*2)+1].dwValueSize = sizeof(DWORD);
nsclass[(i*2)+1].lpValue = &dwUniqueId;
}
}
// Install the service class
//
ret = WSAInstallServiceClass(&sci);
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEALREADY)
{
printf("Service class already registered\n");
bRet = TRUE;
}
else
{
printf("WSAInstallServiceClass() failed: %d\n",
WSAGetLastError());
bRet = FALSE;
}
}
GlobalFree(nsclass);
return bRet;
}
//
// Function: GetIPInterfaceList
//
// Description:
// This function returns an array of SOCKADDR_IN structures,
// one for every local IP interface on the machine. We use
// the ioctl command SIO_GET_INTERFACE_LIST to do this although
// we could have used any number of method such as gethostbyname(),
// SIO_INTERFACE_LIST_QUERY, or the IP helper APIs.
//
SOCKADDR_IN *GetIPInterfaceList(SOCKET s, int *count)
{
static SOCKADDR_IN sa_in[MAX_NUM_CSADDRS];
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -