📄 basic-client.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 + -