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

📄 bclient.cpp

📁 < WINDOWS网络编程>>英文版,一本详细讲解WINDOWS平台下网络编程的国外经典书籍,适合英文水平高的牛人
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Sample: Blocking IPv4/IPv6 Client
//
// Files:
//      bclient.cpp     - this file
//      resolve.cpp     - routines for resovling addresses, etc.
//      resolve.h       - header file for resolve.c
//
// Description:
//      This sample illustrates simple blocking IO for TCP and UDP for
//      both IPv4 and IPv6. This sample uses the getaddrinfo/getnameinfo
//      APIs which allows this application to be IP agnostic. That is the
//      desired address family (AF_INET or AF_INET6) can be determined
//      simply from the string address passed via the -l and -n command.
//
//      For both UDP and TCP, two threads are created: one for sending data
//      and the other for receiving the echoed data. After the send thread
//      sends the specified amount of data it either exits (UDP) or does
//      a shutdown(SD_SEND) (TCP) and exits the thread. The receive thread
//      receives data until the connection is closed or an error occurs.
//
//      For UDP, three zero byte sends are performed after sending the
//      requested data amount. The server will echo these back as well
//      which will indicate to the send thread to exit. Note that UDP
//      is inherently unreliable and therefore if invoked for UDP, the
//      client may not receive all the data send and may hang (as the
//      zero byte sends echoed back could be dropped).
//
//      For example:
//          If this sample is called with the following command lines:
//              bclient.exe -n fe80::2efe:1234 -e 5150
//          Then the client creates an IPv6 socket and attempts to connect
//          to the server at the address given by the -n parameter.
//
//          On the other hand, with the following command line:
//              bclient.exe -n 7.7.7.1 -e 5150
//          Then the server creates an IPv4 socket and attempts to connect
//          to the server specified by the -n parameter.
//
//          Specifying the hostname of the server will attempt to connect
//          to the server via all the addresses returned by DNS (which
//          could be IPv4, IPv6 or both):
//              bclient.exe -n server-name -e 5150
//
// Compile:
//      cl -o bclient.exe bclient.cpp resolve.cpp ws2_32.lib
//
// Usage:
//      bclient.exe [options]
//          -a 4|6     Address family, 4 = IPv4, 6 = IPv6 [default = IPv4]\n"
//          -e port    Port number [default = 5150]\n"
//          -l addr    Local address to bind to [default INADDR_ANY for IPv4 or INADDR6_ANY for IPv6
//          -n addr    Remote address to connect/send to
//          -p proto   Which protocol to use [default = TCP]
//             tcp        Use TCP
//             udp        Use UDP
//          -c         UDP: connect and send (opposed to sendto)
//          -b size    Buffer size (in bytes)
//          -x count   Number of sends to perform
//
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>

#include "resolve.h"

#define DEFAULT_BUFFER_SIZE     4096
#define DEFAULT_SEND_COUNT      100

int gAddressFamily = AF_UNSPEC,             // Address family to use
    gSocketType    = SOCK_STREAM,           // Default to TCP
    gProtocol      = IPPROTO_TCP,
    gBufferSize    = DEFAULT_BUFFER_SIZE,   // Default buffer size for sends
    gSendCount     = DEFAULT_SEND_COUNT;    // Default number of sends to perform

char *gBindAddr    = NULL,                  // Address to bind to locally
     *gServerAddr  = NULL,                  // Server name/address
     *gBindPort    = "5150";                // Port to connect to (on server side)

BOOL  bUdpConnect  = FALSE;                 // Connect the UDP socket before sending?

struct addrinfo *gConnectedEndpoint=NULL;   // Addresses that server name/address resolved to

// Statistics variables
volatile  LONG gBytesRead=0,
               gBytesSent=0,
               gStartTime=0;

//
// Function: usage
//
// Description:
//      Prints usage information and exits the process.
//
void usage(char *progname)
{
    fprintf(stderr, "usage: %s [-a 4|6] [-e port] [-l local-addr] [-n addr] [-p udp|tcp]\n",
            progname);
    fprintf(stderr, 
            "  -a 4|6     Address family, 4 = IPv4, 6 = IPv6 [default = IPv4]\n"
            "  -e port    Port number [default = 5150]\n"
            "  -l addr    Local address to bind to [default INADDR_ANY for IPv4 or INADDR6_ANY for IPv6]\n"
            "  -n addr    Remote address to connect/send to\n"
            "  -p tcp|udp Which protocol to use [default = TCP]\n"
            "  -c         UDP: connect and send (opposed to sendto)\n"
            "  -b size    Buffer size\n"
            "  -x count   Number of sends to perform\n"
           );
    ExitProcess(-1);
}

//
// Function: ValidateArgs
//
// Description:
//      Parses the command line arguments and sets up some global 
//      variables.
//
void ValidateArgs(int argc, char **argv)
{
    int     i;

    for(i=1; i < argc ;i++)
    {
        if (((argv[i][0] != '/') && (argv[i][0] != '-')) || (strlen(argv[i]) < 2))
            usage(argv[0]);
        else
        {
            switch (tolower(argv[i][1]))
            {
                case 'a':               // address family - IPv4 or IPv6
                    if (i+1 >= argc)
                        usage(argv[0]);
                    if (argv[i+1][0] == '4')
                        gAddressFamily = AF_INET;
                    else if (argv[i+1][0] == '6')
                        gAddressFamily = AF_INET6;
                    else
                        usage(argv[0]);
                    i++;
                    break;
                case 'b':               // buffer size
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gBufferSize = atol(argv[++i]);
                    break;
                case 'c':
                    bUdpConnect = TRUE;
                    break;
                case 'e':               // endpoint - port number
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gBindPort = argv[++i];
                    break;
                case 'l':               // local address for binding
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gBindAddr = argv[++i];
                    break;
                case 'n':               // address to connect/send to
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gServerAddr = argv[++i];
                    break;
                case 'p':               // protocol - TCP or UDP
                    if (i+1 >= argc)
                        usage(argv[0]);
                    if (_strnicmp(argv[i+1], "tcp", 3) == 0)
                    {
                        gProtocol = IPPROTO_TCP;
                        gSocketType = SOCK_STREAM;
                    }
                    else if (_strnicmp(argv[i+1], "udp", 3) == 0)
                    {
                        gProtocol = IPPROTO_UDP;
                        gSocketType = SOCK_DGRAM;
                    }
                    else
                        usage(argv[0]);
                    i++;
                    break;
                case 'x':               // sendcount
                    if (i+1 >=argc)
                        usage(argv[0]);
                    gSendCount = atoi(argv[++i]);
                    break;
                default:
                    usage(argv[0]);
                    break;
            }
        }
    }
}

//
// Function: SendThread
//
// Description:
//    This thread sends data on the socket. After all the requested data has
//    been send, the socket is shutdown (for TCP) or three zero byte sends
//    are performed (for UDP). The thread then exits.
//
DWORD WINAPI SendThread(LPVOID lpParam)
{
    SOCKET      s;
    char       *buf=NULL;
    int         buflen,
                nleft,
                idx,
                rc,
                i;

    s = (SOCKET)lpParam;

    // Allocate the send buffer
    buf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BYTE) * gBufferSize);
    if (buf == NULL)
    {
        fprintf(stderr, "ReceiveThread: HeapAlloc failed: %d\n", GetLastError());
        ExitProcess(-1);
    }
    buflen = gBufferSize;

    memset(buf, '#', buflen);

    // Send the requested number of buffers
    for(i=0; i < gSendCount ;i++)
    {
        if ((gProtocol == IPPROTO_TCP) || (bUdpConnect))
        {
            idx = 0;
            nleft = buflen;
            while (nleft > 0)
            {
                rc = send(s, &buf[idx], nleft, 0);
                if (rc == SOCKET_ERROR)
                {
                    fprintf(stderr,"send failed: %d\n", WSAGetLastError());
                    return -1;
                }

                nleft -= rc;
                idx += rc;
            }
            rc = buflen;
        }
        else
        {
            rc = sendto(s, buf, buflen, 0, gConnectedEndpoint->ai_addr, gConnectedEndpoint->ai_addrlen);
            if (rc == SOCKET_ERROR)
            {
                // Its UDP so any failure we encounter is not likely to be serious
                fprintf(stderr, "sendto failed: %d\n", WSAGetLastError());
            }
        }

        // Update bytes sent count
        if (rc > 0)
        {
            InterlockedExchangeAdd(&gBytesSent, rc);
        }
    }

    // If TCP, shutdown the socket to indicate no more sends. For UDP

⌨️ 快捷键说明

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