TCPクライアントテスト

今日のコードは、昨日書いたサーバープログラムに対応するシンプルなメッセージを送るプログラムサンプル。
これも7割方 猫でもわかるネットワークプログラミング 第2版 (猫でもわかるプログラミングシリーズ) のコードをコピペですが、昨日のコードと同じように見えるようにしてみました。
ホストはlocalhostのみ。ポートだけ入力して選べます。(もちろん2行程度の修正でホスト名も入力させるようにはできます!)
ネットワークプログラムって動き始めたら面白い!!

ということで、コード全部は以下に↓

//
// TCPClient.cpp
//

#include "stdafx.h"
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h> // for atoi
#include <conio.h>  // for _getch

#pragma comment ( lib, "WSock32.Lib" )  // WinSock2ライブラリ.

bool
initWinsock()
{
  WSADATA   wsaData;

  // WinSock初期化.
  int       ret = WSAStartup( MAKEWORD(1,1), &wsaData );
  if( ret != 0 ){
    printf( "!! WSAStartupエラーです [%d]\n", ret );
    _getch();
    return false;
  }

  return true;
}

void
termWinsock()
{
  WSACleanup();
}

SOCKET
connectServer( const char* pHost, const u_short& port )
{
  SOCKET        socket_server;
  int           ret;
  HOSTENT*      lpHost;
  unsigned int  addr;
  SOCKADDR_IN   saddr;

  // ソケットオープン.
  socket_server = socket( AF_INET, SOCK_STREAM, 0 );
  if( socket_server < 0 ){
    printf("!! socketエラーです [%s]\n", pHost);
    return INVALID_SOCKET;
  }

  lpHost = gethostbyname( pHost );
  if( lpHost == NULL ){
    addr = inet_addr( pHost );
    lpHost = gethostbyaddr( (char*)&addr, 4, AF_INET );
  }
  if( lpHost == NULL ){
    printf("!! エラーです [%s]\n", pHost);
    closesocket(socket_server);
    return INVALID_SOCKET;
  }

  memset( &saddr, 0, sizeof(SOCKADDR_IN) );
  saddr.sin_port = htons( port );
  saddr.sin_family = lpHost->h_addrtype;
  saddr.sin_addr.s_addr = *((u_long*)lpHost->h_addr);

  ret = connect( socket_server, (SOCKADDR*)&saddr, sizeof(saddr) );
  if( ret == SOCKET_ERROR ){
    printf("!! connectエラーです.[%d] .. [%d]\n", port, ret);
    closesocket(socket_server);
    return INVALID_SOCKET;
  }

  return socket_server;
}

void
testTCPClient_port( const char* pHost, const u_short& port )
{
  SOCKET    socket_server = connectServer( pHost, port );
  if( socket_server ==INVALID_SOCKET ){
    // サーバーへの接続に失敗.
    printf( "# サーバーへの接続に失敗しました.\n" );
    return;
  }

  printf( "# サーバー(%s:%d)へ接続しました('.'で終了)\n", pHost, port );

  char    szBuff[1024];
  while( true ){
    printf( "送信 > " );
    gets_s( szBuff, sizeof(szBuff) );
    
    send( socket_server, szBuff, (int)strlen(szBuff), 0 );

    // 終了.
    if( szBuff[0] == '.' ){
      printf( "quited.\n" );
      break;
    }
  }

  shutdown( socket_server, SD_BOTH );
  closesocket( socket_server );

  return;
}

void
testTCPClient()
{
  char  aHost[] = "localhost";
  char  szPort[1024];

  while( true ){
    printf( "ポート番号を入力してください > " );
    gets_s( szPort, sizeof(szPort) );

    u_short aPort = (u_short)atoi( szPort );
    if( aPort > 0 ){
      testTCPClient_port( aHost, aPort );
    }
    else{
      printf( "# クライアントを終了します.\n" );
      break;
    }
  }
}

int
_tmain(int argc, _TCHAR* argv[])
{
  if( initWinsock() ){
    testTCPClient();
  }
  termWinsock();

  return 0;
}