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

📄 rnrcs.c

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