📄 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
//
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <svcguid.h>
#include <wsipx.h>
#include <wsnwlink.h>
#include <nspapi.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?
DWORD dwNameSpace, // Name space to register on
dwSapId; // Used to create a GUID
SOCKET socks[MAX_NUM_SOCKETS]; // Socket handles for our server
HANDLE hEvents[MAX_NUM_SOCKETS];
BOOL ClientSend(int socktype, int proto, SOCKADDR *server,
int len, int count);
char *FormatIPXAddr(SOCKADDR_IPX *addr);
//
// Function: usage
//
// Description:
// Print usage information.
//
void usage(char *progname)
{
printf("usage: %s -c:Service -s -t:ID -n:[NS_ALL|NS_NTDS|NS_SAP]\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 SAP ID to register under\n");
printf(" This is arbitrary...just needed to create a GUID\n");
printf(" -n:NameSpace Name space to register service under\n");
printf(" Can be one of the strings: NS_ALL, NS_NTDS, or NS_SAP\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
//
strcpy(szServerName, DEFAULT_SERVER_NAME);
dwNameSpace = NS_ALL;
dwSapId = 200;
for(i=0; i < MAX_NUM_SOCKETS ;i++)
socks[i] = SOCKET_ERROR;
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 (strlen(argv[i]) > 3)
dwSapId = atoi(&argv[i][3]);
break;
case 'c': // Client, query for given service
bServer = FALSE;
if (strlen(argv[i]) > 3)
strcpy(szServerName, &argv[i][3]);
break;
case 's': // Server, register as the given service
bServer = TRUE;
if (strlen(argv[i]) > 3)
strcpy(szServerName, &argv[i][3]);
break;
case 'n': // Name spaces to register service under
if (!strnicmp("NS_NTDS", &argv[i][3], strlen("NS_NTDS")))
dwNameSpace = NS_NTDS;
else if (!strnicmp("NS_SAP", &argv[i][3], strlen("NS_SAP")))
dwNameSpace = NS_SAP;
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)
{
// Currently we only support SAP or NTDS name spaces
// so ignore anything else (like DNS)
//
case NS_SAP:
case NS_NTDS:
memcpy(&nsinfocpy[j++], &nsinfo[i], sizeof(WSANAMESPACE_INFO));
break;
}
}
// Free the original buffer and return our copy of useable name spaces
//
GlobalFree(pbuf);
printf("Found %d useable name spaces\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 dwZero=0,
dwUdpPort=0;
char szServiceClassName[64];
int i,
ret;
// Generate a name of our service class
//
wsprintf(szServiceClassName, "ServiceClass: %003d", dwSapId);
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;
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 = &dwZero;
if (nsinfo[i].dwNameSpace == NS_NTDS)
{
// If NS_NTDS is available we will be running a UDP
// based service on the given port number
//
printf("Setting NS_NTDS info...\n");
nsclass[(i*2)+1].lpszName = SERVICE_TYPE_VALUE_UDPPORT;
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 = &dwUdpPort;
}
else if (nsinfo[i].dwNameSpace == NS_SAP)
{
// If NS_SAP is available we will run an IPX based
// service on the given SAP ID
//
printf("Setting NS_SAP info...\n");
nsclass[(i*2)+1].lpszName = SERVICE_TYPE_VALUE_SAPID;
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 = &dwSapId;
}
}
// Install the service class
//
ret = WSAInstallServiceClass(&sci);
if (ret == SOCKET_ERROR)
{
printf("WSAInstallServiceClass() failed: %d\n",
WSAGetLastError());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -