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

📄 basic-client.cpp

📁 SDK FAQ集
💻 CPP
字号:
/***********************************************************************
 basic-client.cpp - Implements a fairly basic Winsock client program
    that initiates a blocking TCP connection to an echo server, sends 
    some data, prints the reply, and dies.

 Compiling:
    VC++: cl -GX basic-client.cpp main.cpp ws-util.cpp wsock32.lib
    BC++: bcc32 basic-client.cpp main.cpp ws-util.cpp
    
 This program is hereby released into the public domain.  There is
 ABSOLUTELY NO WARRANTY WHATSOEVER for this product.  Caveat hacker.
***********************************************************************/

#include <iostream.h>
#include <winsock2.h>
#include "ws-util.h"


//// Constants /////////////////////////////////////////////////////////

// kBufferSize must be larger than the length of kpcEchoMessage.
const int kBufferSize = 1024;
const char* kpcEchoMessage = "This is a test of the emergency data "
        "transfer system.  If this had been real a real emergency, we "
        "would have sent this data out-of-band.";
        

//// Prototypes ////////////////////////////////////////////////////////

u_long LookupAddress(const char* pcHost);
SOCKET EstablishConnection(u_long nRemoteAddr, u_short nPort);
int SendEcho(SOCKET sd);


//// DoWinsock /////////////////////////////////////////////////////////
// The module's driver function -- we just call other functions and
// interpret their results.

int DoWinsock(const char* pcHost, int nPort)
{
    cout << "Looking up address..." << flush;
    u_long nRemoteAddress = LookupAddress(pcHost);
    if (nRemoteAddress == INADDR_NONE) {
        cerr << endl << WSAGetLastErrorMessage("lookup address") << 
                endl;
        return 3;
    }
    in_addr Address;
    memcpy(&Address, &nRemoteAddress, sizeof(u_long)); 
    cout << inet_ntoa(Address) << ":" << nPort << endl; 

    cout << "Connecting to remote host..." << flush;
    SOCKET sd = EstablishConnection(nRemoteAddress, htons(nPort));
    if (sd == INVALID_SOCKET) {
        cerr << endl << WSAGetLastErrorMessage("connect to server") << 
                endl;
        return 3;
    }
    cout << "connected, socket " << sd << "." << endl;
    
    cout << "Sending echo packet..." << flush;
    int nBytes;
    if ((nBytes = SendEcho(sd)) < 0) {
        cerr << endl << WSAGetLastErrorMessage("send echo packet") <<
                endl;
        return 3;
    }
    else if (nBytes == 0) {
        cerr << endl << "Remote peer closed connection unexpectedly." <<
                endl;
    }
    else {
        cout << "server sent back " << nBytes << " bytes." << endl;
        if (nBytes == kBufferSize) {
            cerr << "FYI, likely data overflow." << endl;
        }
    }

    cout << "Shutting connection down..." << flush;
    if (ShutdownConnection(sd)) {
        cout << "Connection is down." << endl;
    }
    else {
        cout << endl << WSAGetLastErrorMessage("Shutdown connection") <<
                endl;
    }

    cout << "All done!" << endl;

    return 0;
}


//// LookupAddress /////////////////////////////////////////////////////
// Given an address string, determine if it's a dotted-quad IP address
// or a domain address.  If the latter, ask DNS to resolve it.  In
// either case, return resolved IP address.  If we fail, we return
// INADDR_NONE.

u_long LookupAddress(const char* pcHost)
{
    u_long nRemoteAddr = inet_addr(pcHost);
    if (nRemoteAddr == INADDR_NONE) {
        // pcHost isn't a dotted IP, so resolve it through DNS
        hostent* pHE = gethostbyname(pcHost);
        if (pHE == 0) {
            return INADDR_NONE;
        }
        nRemoteAddr = *((u_long*)pHE->h_addr_list[0]);
    }

    return nRemoteAddr;
}


//// EstablishConnection ///////////////////////////////////////////////
// Connects to a given address, on a given port, both of which must be
// in network byte order.  Returns newly-connected socket if we succeed,
// or INVALID_SOCKET if we fail.

SOCKET EstablishConnection(u_long nRemoteAddr, u_short nPort)
{
    // Create a stream socket
    SOCKET sd = socket(AF_INET, SOCK_STREAM, 0);
    if (sd != INVALID_SOCKET) {
        sockaddr_in sinRemote;
        sinRemote.sin_family = AF_INET;
        sinRemote.sin_addr.s_addr = nRemoteAddr;
        sinRemote.sin_port = nPort;
        if (connect(sd, (sockaddr*)&sinRemote, sizeof(sockaddr_in)) ==
                SOCKET_ERROR) {
            sd = INVALID_SOCKET;
        }
    }

    return sd;
}


//// SendEcho //////////////////////////////////////////////////////////
// Sends the echo packet to the server, waits for, and verifies reply.
// Returns 0 if remote peer closes connection, > 0 if we sent data
// successfully, and < 0 on error.

int SendEcho(SOCKET sd)
{
    // Send the string to the server
    const int kEchoMessageLen = strlen(kpcEchoMessage);
    if (send(sd, kpcEchoMessage, kEchoMessageLen, 0) == SOCKET_ERROR) {
        return -1;
    }

    // Read reply from server
    char acReadBuffer[kBufferSize];
    int nTotalBytes = 0;
    while (nTotalBytes < kEchoMessageLen) {
        int nNewBytes = recv(sd, acReadBuffer + nTotalBytes, 
                kBufferSize - nTotalBytes, 0);
        if (nNewBytes == SOCKET_ERROR) {
            return -1;
        }
        else if (nNewBytes == 0) {
            cerr << "Connection closed by peer." << endl;
            return 0;
        }

        nTotalBytes += nNewBytes;
    }

    // Check data for sanity
    if (strncmp(acReadBuffer, kpcEchoMessage, nTotalBytes) != 0) {
        cerr << "Mismatch in data received from server. " <<
                "Something's broken!" << endl;
    }

    return nTotalBytes;
}

⌨️ 快捷键说明

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