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

📄 wsnbclnt.cpp

📁 < WINDOWS网络编程>>英文版,一本详细讲解WINDOWS平台下网络编程的国外经典书籍,适合英文水平高的牛人
💻 CPP
字号:
// Module Name: wsnbclnt.cpp
//
// Description:
//    This sample illustrates how to use the AF_NETBIOS protocol family
//    from a Winsock application. This particular sample is a client 
//    that communicates with to the server (wsnbsvr.c) sample.
//
// Compile:
//    cl -o wsnbclnt wsnbclnt.cpp ws2_32.lib
//
// Command Line Parameters/Options:
//    wsnbclnt.exe options
//
//    -n NAME  - Server's Netbios name 
//    -p PORT  - Use this integer value as the 16th byte of server name
//    -l LANA  - Attempt a connection on this LANA number only, the
//               default behavior is to attempt a connection on all
//               LANA numbers
//    -t TYPE  - Specifies datagram (d) or seqpacket (s)
//    -c COUNT - Number of types to send the message
//    -b SIZE  - Size of buffer to send
//
#include <winsock2.h>
#include <wsnetbs.h>

#include <stdio.h>
#include <stdlib.h>

//
// A couple common definitions used between client and server
//
#include "wsnbdef.h"

char    szServerName[NETBIOS_NAME_LENGTH];   // Our NetBIOS name
int     iPort,                               // Our 16th byte
        iLana,                               // LANA to connect on
        iSocketType=SOCK_SEQPACKET;          // Datagram or stream?
DWORD   dwCount=DEFAULT_COUNT,               // How many packets
        dwSize=MAX_BUFFER;                   // Size of buffer to send
BOOL    bOneLana=FALSE;                      // Connect on one LANA

//
// Function: usage
// 
// Description:
//    Print out usage information.
//
void usage()
{
    printf("usage: wsnbclnt -n str -p int -l int -t char\n");
    printf("       -n NAME        Our NetBIOS name\n");
    printf("       -p PORT        The 16th byte qualifier of our name\n");
    printf("       -l LANA        Specifies to connect on this LANA only\n");
    printf("                       By default attempt connection on all LANAs\n");
    printf("       -t TYPE        Specifies datagram (d) or seqpacket (s)\n");
    printf("       -c COUNT       Number of types to send the message\n");
    printf("       -b SIZE        Size of buffer to send\n");
    ExitProcess(1);
}

//
// Function: ValidateArgs
//
// Description
//    Parse the argument list for our NetBIOS name and whether
//    we want to operate on all LANAs or just one.
//
void ValidateArgs(int argc, char **argv)
{
    int                i;


    if (argc > 1)
    {
        for (i = 1; i < argc; i++)
        {
            if ( (argv[i][0] == '-') || (argv[i][0] == '/')  )
            {
                switch (tolower(argv[i][1]) )
                {
                    case '?':
                        usage();
                        break;
                    case 'n':   // use a unique name
                        if (i+1 < argc)
                        {
                            strncpy(szServerName,argv[i+1],NETBIOS_NAME_LENGTH);
                            if (0 != strlen(szServerName)) 
                                ++i;
                        }
                        break;

                    case 'p':   // set the 16th byte
                        if (i+1 < argc)
                        {
                            iPort = atoi(argv[i+1]);
                            ++i;
                        }
                        break;

                    case 'l':   // connect on one lana only
                        if (i+1 < argc)
                        {
                            bOneLana = TRUE;
                            if (strlen(argv[i+1]) > 3)
                                iLana = atoi(argv[i+1]);
                            ++i;
                        }
                        break;

                    case 't':   // datagram or stream socket?
                        if (i+1 < argc)
                        {
                            if ('s' == tolower(argv[i+1][0]))
                                iSocketType = SOCK_SEQPACKET;
                            else if ('d' == tolower(argv[i+1][0]))
                                iSocketType = SOCK_DGRAM;
                            else
                                usage();

                            ++i;
                        }
                        break;

                    case 'c':   // num types to send message
                        if (i+1 < argc)
                        {
                            dwCount = atol(argv[i+1]);
                            ++i;
                        }

                        break;

                    case 'b':   // size of send buffer
                        if (i+1 < argc)
                        {
                            dwSize = (atol(argv[i+1]) > MAX_BUFFER ? 
                                    MAX_BUFFER : atol(argv[i+1]));
                            ++i;
                        }
                        break;

                    default:
                        usage();
                        break;
                } 
            }
        } 

    }

    return;
}

//
// Function: main
//
// Description:
//    This function parses the command line arguments, loads the
//    Winsock library, and connects to a server. By default, a
//    connection is attempted on all available LANA numbers. The
//    first one to succeed is used and the others are cancelled.
//
int main(int argc, char **argv)
{
    WSADATA           wsd;
    SOCKET           *socks=NULL;           // array of socket handles
    WSAEVENT         *hEvents=NULL;         // events for each socket
    SOCKADDR_NB       nbaddr;               // NetBIOS addr of server
    WSAPROTOCOL_INFO *wsapi=NULL;
    DWORD             dwRet,
                      dwNumProtocols,
                      dwIndex,
                      dwErr,
                      i;
    char              szMessage[MAX_BUFFER];   // Data buffer
    unsigned long     iOptVal;
    struct fd_set     fdread;

    // Validate arguments
    //
    ValidateArgs(argc, argv);

    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
    {
        printf("Unable to load Winsock!\n");
        return 1;
    }
    // If we're connecting on all LANAs enumerate all AF_NETBIOS
    //  protocols; if not we can just specify the LANA we want
    //  when creating the socket.
    //
    if (bOneLana == FALSE)
    {
        // This function will return an array of WSAPROTOCOL_INFO
        //  structures that match our socket type
        //
        if (FindProtocol(&wsapi, &dwNumProtocols) != TRUE)
        {
            printf("Unable to find correct protocol!\n");
            return 1;
        }

        CullInvalidProviders(wsapi, &dwNumProtocols);

        if (dwNumProtocols == 0)
        {
            printf("No NetBIOS capable providers found!\n");
            return 1;
        }
    } 
    else
    {
        dwNumProtocols = 1;
    }
    // Setup the NetBIOS address name
    //
    SET_NETBIOS_SOCKADDR(&nbaddr, NETBIOS_UNIQUE_NAME, szServerName, 
            iPort); 
    //
    // Allocate some global structures. 
    //  socks : array of SOCKET handles for each transport we connect on
    //  hEvents : array of WSAEVENT handles for event notification
    //
    socks = (SOCKET *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
            sizeof(SOCKET) * dwNumProtocols);
    if (socks == NULL)
    {
        printf("out of memory\n");
        return 1;
    }
    hEvents = (WSAEVENT *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
            sizeof(WSAEVENT) * dwNumProtocols);
    if (hEvents == NULL)
    {
        printf("out of memory\n");
        return 1;
    }
    // For each LANA, create a WSAEVENT, create the SOCKET, and
    //  register it for what events we want to receive.
    //
    for (i=0; i < dwNumProtocols ;i++)
    {
        if (bOneLana)
            printf("Transport LANA: %d\n", iLana);
        else
            printf("Transport: '%s'\n", wsapi[i].szProtocol);
        hEvents[i] = WSACreateEvent();
        if (hEvents[i] == NULL)
        {
            printf("WSACreateEvent failed: %d\n", WSAGetLastError());
            return 1;
        }
        if (bOneLana == FALSE)
            socks[i] = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
                    FROM_PROTOCOL_INFO, &wsapi[i], 0, WSA_FLAG_OVERLAPPED);
        else
            socks[i] = WSASocket(AF_NETBIOS, SOCK_SEQPACKET, -iLana, NULL,
                    0, WSA_FLAG_OVERLAPPED); 

        if (socks[i] == INVALID_SOCKET)
        {
            printf("socket() failed: %d\n", WSAGetLastError());
            return 1; 
        }

        if (WSAConnect(socks[i], (SOCKADDR *)&nbaddr, sizeof(nbaddr),
                    NULL, NULL, NULL, NULL) == SOCKET_ERROR)
        {
            printf("WSACOnnect failed: %d\n", WSAGetLastError());
            continue;
        }
        if (WSAEventSelect(socks[i], hEvents[i], FD_CONNECT) == 
                SOCKET_ERROR)
        {
            printf("WSAEventSelect failed: %d\n", WSAGetLastError());
            return 1;
        }
    }
    // Wait for one of the connects to succeed
    //
    dwIndex = WSAWaitForMultipleEvents(dwNumProtocols, hEvents, FALSE, 
            WSA_INFINITE, FALSE);
    if (dwIndex == WSA_WAIT_FAILED)
    {
        printf("WSAWaitForMultipleEvents failed: %d\n", WSAGetLastError());
        return 1;
    }
    // Close the sockets of all other pending connections other than the
    //  one that completed first
    //
    dwIndex -= WAIT_OBJECT_0;
    for (i=0; i < dwNumProtocols ;i++)
    {
        if (i != dwIndex)
            closesocket(socks[i]);
    }
    // Put the socket in non-blocking mode
    //
    iOptVal = 1L;
    if (ioctlsocket(socks[dwIndex], FIONBIO, &iOptVal) == SOCKET_ERROR)
    {
        printf("ioctlsocket(FIONBIO) failed: %d\n", WSAGetLastError());
    }
    memset(szMessage, 'a', dwSize);
    for (i=0; i < dwCount ;i++)
    {
        // Send the message to the server
        //
        dwRet = send(socks[dwIndex], szMessage, dwSize, 0);
        if (dwRet == 0)
        {
            printf("graceful close\n");
            closesocket(socks[dwIndex]);
            return 0;
        } else if (dwRet == SOCKET_ERROR)
        {
            if ((dwErr = WSAGetLastError()) == WSAEWOULDBLOCK)
            {
                i--;
                continue;
            } else
            {
                printf("send failed: %d\n", dwErr);
                return 1;
            }
        }
        printf("Wrote %d bytes\n", dwRet);
        //
        // Wait until the server echoes the data back. This really doesn't 
        //  matter when using SOCK_SEQPACKET, but if we're using SOCK_DGRAM
        //  then our recv() would fail with WSAEWOULDBLOCK and we'd skip
        //  the returned data (as the server might not have sent it yet)
        //
        FD_ZERO(&fdread);
        FD_SET(socks[dwIndex], &fdread);
        select(0, &fdread, NULL, NULL, NULL);

        //
        // Read the message back
        //
        dwRet = recv(socks[dwIndex], szMessage, MAX_BUFFER, 0);
        if (dwRet == 0)
        {
            printf("graceful close\n");
            closesocket(socks[dwIndex]);
            return 0;
        } else if (dwRet == SOCKET_ERROR)
        {
            if ((dwErr = WSAGetLastError()) == WSAEWOULDBLOCK)
            {
                i--;
                continue;
            } else
            {
                printf("recv() failed: %d\n", dwErr);
                return 1;
            }
        }
        printf("Read %d bytes\n", dwRet);
    }

    closesocket(socks[dwIndex]);

    for (i=0; i < dwNumProtocols ;i++)
        WSACloseEvent(hEvents[i]);

    GlobalFree(wsapi);
    GlobalFree(socks);
    GlobalFree(hEvents);

    WSACleanup();
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -