サンプル集  >  VC  >  winsock2 A
winsock2 A
2010/01/06

>> winsock2 からの続き

前回作った winsock2 を使った通信プログラムでは IP、ポートを直に書いていました。 これを外部の ini ファイルから取得するようにします。

◆環境
OS Windows XP Professional Version 2002 Service Pack 3
VC Microsoft Visual Studio 2008 Version 9.0.30729.1 SP

ini ファイルの値は GetPrivateProfileString 関数で取得します。

まずはサーバー側のプログラムを修正します。

winsock2TestServer.cpp
  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
// winsock2TestServer.cpp : メイン プロジェクト ファイルです。

#include "stdafx.h"
#include "winsock2.h"
#include <iostream>
using namespace std;

using namespace System;

#pragma comment( lib, "ws2_32.lib" )

int main(array<System::String ^> ^args)
{
    wchar_t port_number[10];
    DWORD val =
    GetPrivateProfileString( L"TCPIP"
                           , L"Port_Number"
                           , L"NULL"
                           , &port_number[0]
                           , sizeof( port_number )
                           , L"./winsock2TestServer.ini"
                           );
    wprintf( L"%s\n", port_number );

    wchar_t listen_number[10];
    GetPrivateProfileString( L"TCPIP"
                           , L"Listen_Number"
                           , L"NULL"
                           , &listen_number[0]
                           , sizeof( listen_number )
                           , L"./winsock2TestServer.ini"
                           );
    wprintf( L"%s\n", listen_number );

    WSADATA wsaData;
    int     ret;
    SOCKET  sock;
    int     len;
    SOCKET  client_sock;

    struct sockaddr_in addr;
    struct sockaddr_in client;

    // winsock2の初期化
    ret = WSAStartup( MAKEWORD( 2, 0 ), &wsaData );
    if ( ret != 0 )
    {
        switch( ret )
        {
        case WSASYSNOTREADY:
            printf( "WSASYSNOTREADY\n" );
            break;
        case WSAVERNOTSUPPORTED:
            printf( "WSAVERNOTSUPPORTED\n" );
            break;
        case WSAEINPROGRESS:
            printf( "WSAEINPROGRESS\n" );
            break;
        case WSAEPROCLIM:
            printf( "WSAEPROCLIM\n" );
            break;
        case WSAEFAULT:
            printf( "WSAEFAULT\n" );
            break;
        default:
            break;
        }
        exit( -1 );
    }
    printf( "WSAStartup successful.\n" );

    // ソケットの作成
    sock = socket( AF_INET, SOCK_STREAM, 0 );
    if ( sock == INVALID_SOCKET )
    {
        printf( "error : %d\n", WSAGetLastError() );
        exit( -2 );
    }
    printf( "socket successful.\n" );

    // ソケットの設定
    addr.sin_family = AF_INET;
    addr.sin_port = htons( _wtoi( port_number ) );
    addr.sin_addr.S_un.S_addr = INADDR_ANY;
    ret = bind( sock
              , ( struct sockaddr* )&addr
              , sizeof( addr )
              );
    if ( ret == SOCKET_ERROR )
    {
        printf( "error : %d\n", WSAGetLastError() );
        exit( -3 );
    }
    printf( "bind successful.\n" );

    // TCPクライアントからの接続要求を待てる状態にする
    ret = listen( sock, _wtoi( listen_number ) );
    if ( ret == SOCKET_ERROR )
    {
        printf( "error : %d\n", WSAGetLastError() );
        exit( -4 );
    }
    printf( "listen successful.\n" );

    // TCPクライアントからの接続要求を受け付ける
    len = sizeof( client );
    client_sock = accept( sock
                        , ( struct sockaddr* )&client
                        , &len
                        );
    printf( "accepted connection from %s (%d)\n"
          , inet_ntoa( client.sin_addr )
          , ntohs( client.sin_port )
          );

    // メッセージ送信
    char* msg = "HELLO winsock2!!";
    send( client_sock, msg, strlen( msg ), 0 );

    // TCPセッションの終了
    closesocket( client_sock );

    // winsock2の終了処理
    WSACleanup();
    printf( "WSACleanup successful.\n" );

    return 0;
}

サーバー側の ini ファイルは以下のようになります。

winsock2TestServer.ini
1: 
2: 
3: 
[TCPIP]
Port_Number="12345"
Listen_Number="5"

続いてクライアント側のプログラムを修正します。

winsock2TestClient.cpp
  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
// winsock2TestClient.cpp : メイン プロジェクト ファイルです。

#include "stdafx.h"
#include "winsock2.h"
#include <comdef.h>
#include <iostream>
using namespace std;

using namespace System;

#pragma comment( lib, "ws2_32.lib" )

int main(array<System::String ^> ^args)
{
    wchar_t port_number[10];
    DWORD val =
    GetPrivateProfileString( L"TCPIP"
                           , L"Port_Number"
                           , L"NULL"
                           , &port_number[0]
                           , sizeof( port_number )
                           , L"./winsock2TestClient.ini"
                           );
    wprintf( L"%s\n", port_number );

    wchar_t server_ip_address[20];
    GetPrivateProfileString( L"TCPIP"
                           , L"Server_IP_Address"
                           , L"NULL"
                           , &server_ip_address[0]
                           , sizeof( server_ip_address )
                           , L"./winsock2TestClient.ini"
                           );
    wprintf( L"%s\n", server_ip_address );

    WSADATA wsaData;
    int     ret;
    SOCKET  sock;
    char    buf[32];

    struct sockaddr_in server;

    ret = WSAStartup( MAKEWORD( 2, 0 ), &wsaData );
    if ( ret != 0 )
    {
        switch( ret )
        {
        case WSASYSNOTREADY:
            printf( "WSASYSNOTREADY\n" );
            break;
        case WSAVERNOTSUPPORTED:
            printf( "WSAVERNOTSUPPORTED\n" );
            break;
        case WSAEINPROGRESS:
            printf( "WSAEINPROGRESS\n" );
            break;
        case WSAEPROCLIM:
            printf( "WSAEPROCLIM\n" );
            break;
        case WSAEFAULT:
            printf( "WSAEFAULT\n" );
            break;
        default:
            break;
        }
        exit( -1 );
    }
    printf( "WSAStartup successful.\n" );

    sock = socket( AF_INET, SOCK_STREAM, 0 );
    if ( sock == INVALID_SOCKET )
    {
        printf( "error : %d\n", WSAGetLastError() );
        exit( -2 );
    }
    printf( "socket successful.\n" );

    // 接続先指定用構造体の準備
    server.sin_family = AF_INET;
    server.sin_port = htons( _wtoi( port_number ) );
    server.sin_addr.S_un.S_addr
    = inet_addr( ( const char* )_bstr_t( server_ip_address ) );

    // サーバに接続
    connect( sock
           , ( struct sockaddr* )&server
           , sizeof( server )
           );

    // サーバからデータを受信
    memset( buf, 0, sizeof( buf ) );
    int n = recv( sock, buf, sizeof( buf ), 0 );
    if ( n == SOCKET_ERROR )
    {
        switch( WSAGetLastError() )
        {
        case WSAENOTCONN:
            printf( "ソケットが接続されていません。\n" );
            exit( -10 );
        default:
            printf( "error : %d\n", WSAGetLastError() );
            exit( -11 );
        }
    }
    printf( "%d, %s\n", n, buf );

    // winsock2の終了処理
    WSACleanup();
    printf( "WSACleanup successful.\n" );

    return 0;
}

クライアント側の ini ファイルは以下のようになります。

winsock2TestClient.ini
1: 
2: 
3: 
[TCPIP]
Port_Number="12345"
Server_IP_Address="127.0.0.1"

ビルド後、前回と同じくサーバー -> クライアントの順で実行したら上手く動作しました。

送信する文字が今は「HELLO winsock2!!」を直に書いていますので、これを標準入力から取り込むようにしたいと思います。

▲ PageTop  ■ Home


Copyright (C) 2012 ymlib.com