TCPサーバーテスト

TCPのメッセージを受信する簡易サーバープログラム。
と言っても参考にしている 猫でもわかるネットワークプログラミング 第2版 (猫でもわかるプログラミングシリーズ) のコードをコピペして、あれこれ修正したもの。

この本を参考にしたら結構簡単に出来た。
他にもUDPとかFTPもコピペしてコンパイルしてみたりしてみたのだけど、割と簡単に作れてしまうので楽しい。
(と言ってもあくまでもメッセージ受信のテスト用なので、コピペして使用するには注意してください。)
ということで、コード。↓

//
// TCPServer.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
waitClient( const u_short& port )
{
  SOCKET    client_socket = INVALID_SOCKET;

  int     ret;
  SOCKET    listen_s;
  SOCKADDR_IN saddr;
  SOCKADDR_IN from;
  int     fromlen = (int)sizeof(from);
  
  // listen用ソケットオープン.
  listen_s  = socket( AF_INET, SOCK_STREAM, 0 );
  if( listen_s < 0 ){
    printf( "!! socketエラーです [%d]\n", listen_s);
    return INVALID_SOCKET;
  }

  memset( &saddr, 0, sizeof(SOCKADDR_IN) );
  saddr.sin_port = htons( port );
  saddr.sin_family = AF_INET;
  saddr.sin_addr.s_addr = htonl( INADDR_ANY );

  ret = bind( listen_s, (struct sockaddr *)&saddr, sizeof(saddr) );
  if( ret == SOCKET_ERROR ){
    // 多分別のアプリがポートを使用している.
    printf( "!! bindエラーです (PORT:%d) .. [%d]\n", port, ret );
    return INVALID_SOCKET;
  }

  // listen用のソケットの指定.
  if( listen( listen_s, 0 ) == SOCKET_ERROR ){
    printf( "!! listen エラーです.\n" );
    closesocket( listen_s );
    return INVALID_SOCKET;
  }
  
  printf( "# ポート:%d で接続を待っています.\n", port );

  // 接続待ちでブロックします.
  client_socket = accept( listen_s, (SOCKADDR*)&from, &fromlen );
  if( client_socket ==INVALID_SOCKET ){
    printf("!! accept error .. [%d]\n", port );
  }
  else{
    printf( "# クライアントが接続[%s]\n", inet_ntoa(from.sin_addr) );
  }

  closesocket( listen_s );

  return client_socket;
}

void
testTCPServer_port( const u_short& port )
{
  char    szBuff[1024];
  int     nRcv;

  SOCKET    client_socket = waitClient( port );
  if( client_socket ==INVALID_SOCKET ){
    // クライアントの接続に失敗.
    return;
  }

  while( true ){
    // クライアントからのメッセージ受信のためにブロックします.
    nRcv = recv( client_socket, szBuff, sizeof(szBuff)-1, 0 );

    if( nRcv == SOCKET_ERROR ){
      printf( "!! recvエラーです. [%d]\n", nRcv );
      break;
    }
    else if( nRcv == 0 ){
      printf( "# クライアントが切断しました.\n" );
      break;
    }

    szBuff[nRcv] = '\0';
    printf( "> [%s]\n", szBuff );
  }

  shutdown( client_socket, SD_BOTH );
  closesocket( client_socket );

  return;
}

void
testTCPServer()
{
  char szPort[1024];

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

    u_short aPort = (u_short)atoi( szPort );
    if( aPort > 0 ){
      testTCPServer_port( aPort );
    }
    else{
      printf( "# サーバーを終了します.\n" );
      break;
    }
  }
}

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

  return 0;
}