⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rnrcs.c

📁 《Windows网络编程技术》附书源码源码. 运行环境:9x/Me/NT/2000/XP/ 源码语言:简体中文 第十章
💻 C
📖 第 1 页 / 共 3 页
字号:
// 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 + -