ウィンドウソケットエラー処理


エラー処理方法によっては,温属関数は以下の3種類に分類できる.
  • エラーを処理する必要がない場合:一部のソケット関数が値を返さなかったり、呼び出しが行われなかったりした場合、常に成功
  • 戻り値のみ使用エラー:WSAStartup()関数
  • 戻り値を使用してエラーをチェックする場合は、エラーコードを使用して詳細を確認します.ほとんどのソケット関数
  • これは第1のタイプと第2のタイプの特殊な状況であるため,ほとんどのソケット関数に適用される最後のタイプをどのように処理するかについて議論する.
    ソケット関数呼び出し結果にエラーが発生した場合は、WSAGetLastError()関数を使用して抽出コードを取得できます.
    int WSAGetLastError(void);
    使用例は次のとおりです.
    if (소켓 함수(...) == 실패)
    {
    	int errcode = WSAGetLastError();
        printf(errcode에 해당하는 오류 메세지);
    }
    WSAGetLastError()関数の戻り値を画面に直接表示する場合は、これらのコードの意味をユーザーが直接理解する必要があります.したがって、クラスコードに対応するエラーメッセージを出力することが望ましい.FormatMessage()関数を使用して、エラー・コードに対応するエラー・メッセージを取得します.この関数のパラメータが取ることができる様々な値と意味は、MSDN(visualstudier 2008以降)またはvisualstudioドキュメント(visualstudio 2010以降)を参照することができる.ここでは主に最も一般的なパラメータ値について説明します.
    // 성공: 오류 메세지 길이, 실패: 0
    DWORD FromatMessage(
    	DWORD dwFlags,
        LPCVOID lpSource,
        DWORD dwMessageId,
        DWORD dwLanguageId,
        LPTSTR lpBuffer,
        DWORD nSize,
        va_list *Arguments
    );
  • dwFlags:FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM値.dwFlagsをこの値に設定すると、lpSourceNULL値、nSizeに0、ArgumentsNULL値を使用できます.
  • FORMAT_MESSAGE_ALLOCATE_BUFFER:これは、FormateMessage()関数が自分でスペースを割り当ててエラーメッセージ
  • を格納することを意味する.
  • FORMAT_MESSAGE_FROM_SYSTEM:オペレーティングシステムからエラーメッセージを取得
  • dwMessageId:エラーコードを表し、MSAGetLastError()関数の戻り値をここに入れます.
  • dwLanguageId:エラーメッセージを表示する言語を示します.MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)コントロールパネルで設定したデフォルト言語を使用してエラーメッセージを取得します.
  • lpBuffer:エラーメッセージの先頭アドレスがここに格納されます.エラーメッセージを格納するスペースはFomatMessage()によって自動的に割り当てられるため、ユーザはアドレス値を格納する変数をここに置くことができる.エラーメッセージの使用が完了したら、LocalFree()関数を使用してシステムに割り当てられたメモリを返すことに注意してください.
  • 上記FormateMessage()関数を適用した要素処理関数err_quit(char *msg)関数を以下に示す.この関数の役割は、現在発生しているエラーメッセージを画面上のメッセージボックスとして表示し、msgパラメータで渡された文字列をパラメータとしてアプリケーションを終了することです.
    void err_quit(char *msg)
    {
    	LPVOID lpMsgBuf;
        FormatMessage(
        	FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
            NULL, WSAGetLastError(),
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) &lpMsgBuf, 0, NULL);
        MessageBox(NULL, (LPCTSTR) lpMsgBuf, msg, MB_ICONERROR);
        LocalFree(lpMsgBuf);
        exit(1);
    }
    使用例は次のとおりです.
    if (socket(...) == INVALID_SOCKET) err_quit("socket()");
    if (bind(...) == SOCKET_ERROR) err_quit("bind()");
    たとえば、bind()関数にエラーが発生した場合は、次のメッセージ・ボックスを画面に表示し、ボタンを押してアプリケーションを終了します.
    (2-1図)
    その他のエラー処理関数err_display()関数は以下のようになります.この関数は、err_quit()関数の最後の行を向上させ、出力関数MessageBox()の代わりにprintf()を使用します.この関数はエラーメッセージを出力しますが、アプリケーションを終了しません.
    小さなエラーの場合、アプリケーションを終了するのは望ましくないので、この場合に使用できます.
    void err_display(char *msg)
    {
    	LPVOID lpMsgBuf;
        FormatMessage(
        	FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
            NULL, WSAGetLastError(),
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) &lpMsgBuf, 0, NULL);
        printf("[%s] %s\n", msg, (char *) lpMsgBuf);
        LocalFree(lpMsgBuf);
    }
    bind()関数にエラーが発生した場合にerr_quit()ではなくerr_display()を使用すると、次のエラーメッセージが出力されます.
    (2-2図)
    参考資料
    金成祐著、「TCP/IPウィンドウソケットプログラミング」、星光学院、2018