サンプル集  >  VC  >  winsock2 I
winsock2 I connectエラー処理追加
2012/09/05

No.409で作成したクライアントプログラムに、connectのエラー処理を追加しました。

◆環境
OS Windows XP Professional Version 2002 Service Pack 3
VC Microsoft Visual C++ 2008 91179-136-7480673-60595

connect関数がSOCKET_ERRORを返した場合、WSAGetLastError関数とperror関数でエラー情報を表示するようにしました。

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: 
113: 
114: 
115: 
116: 
117: 
118: 
// 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 ) );

    // サーバに接続
    int st = connect( sock
                    , ( struct sockaddr* )&server
                    , sizeof( server )
                    );
    if ( st == SOCKET_ERROR )
    {
        printf( "st=%d last=%d\n", st, WSAGetLastError() );
        perror( "connect error!!" );
        exit( -21 );
    }

    // サーバからデータを受信
    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;
}

10001のポートに接続したいのでnetstatコマンドでネットワークの状態を確認します。

>netstat -a -p TCP

Active Connections

  Proto  Local Address          Foreign Address        State
  TCP    ympc1sv001:echo        ympc1sv001.SV001.ymlib.com:0  LISTENING
  TCP    ympc1sv001:discard     ympc1sv001.SV001.ymlib.com:0  LISTENING
  :
  略
  :
  TCP    ympc1sv001:10001       ympc1sv001.SV001.ymlib.com:0  LISTENING
  TCP    ympc1sv001:4021        ympc1sv001.SV001.ymlib.com:0  LISTENING
  :
  略

ポート10001は状態がLISTENINGと表示されています。 接続待ち状態になっていると判断します。

プログラムを実行し接続してみます。

>winsock2TestClient.exe
10001
localhost
WSAStartup successful.
socket successful.
st=-1 last=10061
connect error!!: No error

connectでエラーが出ました。perrorの方は「No error」となっていますが、WSAGetLastErrorは10061というコードを返しています。

10061を調べたところWSAECONNREFUSEがこれに該当し、エラー理由は「実行中のサーバープログラムが存在しない」というものでした。

先ほどnetstatで調べたときポート10001はLISTENINGになっていたので接続できるはずです。

netstatの結果をIPで表示するよう -n オプションを指定して確認します。

>netstat -a -n -p TCP

Active Connections

  Proto  Local Address       Foreign Address        State
  TCP    0.0.0.0:7           0.0.0.0:0              LISTENING
  TCP    0.0.0.0:9           0.0.0.0:0              LISTENING
  :
  略
  :
  TCP    192.168.1.1:10001   0.0.0.0:0              LISTENING
  TCP    192.168.9.1:4021    0.0.0.0:0              LISTENING
  :
  略

ポート10001のローカルIPが192.168.1.1になっていました。 別のポートの4021のローカルIPは192.168.9.1になっています。

今回のテスト用PCはネットワークカードを2枚さしていました。 クライアントは192.168.9.xにいる為、192.168.1.1で待ち受けていてもつながらなかったようです。 192.168.1.1の方のネットワークカードを無効にしてサーバーを再起動したところ待ち受けが192.168.9.1:10001になり接続する事ができました。

▲ PageTop  ■ Home


Copyright (C) 2012 ymlib.com