< error C2275 : typedef 識別子に、クラス メンバ アクセス演算子 (->) を使用しました。 | しょぼ Hash クラス >

January 26, 2006

対数あれこれ

苦手な対数のお勉強だ。

x = n p

のとき、pn を底とする x の対数と呼び、以下のように表記する。

p = log n x

プログラミング言語では、定数 e を底とする自然対数を返す log (number) 関数が定義されていることが多い。任意の数 n を底とした対数が得たければ、以下のようにする。

log n x = log (x) / log (n)

ここで突然、ソケットの話になる。Winsock で、ネットワークイベントを Win32 イベントオブジェクトで受け取る手法がある。

// ソケットを作る
SOCKET s = socket (AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET != s)
{
    // イベントを作る(CreateEvent ()でもよい)
    HANDLE hEvent = WSACreateEvent ();
    if (WSA_INVALID_EVENT != hEvent)
    {
        // connect をイベントで待機する
        int nRet = WSAEventSelect (s, hEvent, FD_CONNECT);
        if (SOCKET_ERROR != nRet)
        {
            // 接続
            struct sockaddr_in RemoteAddr;
            ZeroMemory (&RemoteAddr, sizeof RemoteAddr);
            RemoteAddr.sin_family      = AF_INET;
            RemoteAddr.sin_addr.s_addr = inet_addr ("127.0.0.1");
            RemoteAddr.sin_port        = htons (60000);
            nRet = connect (s, (sockaddr*) &RemoteAddr, sizeof RemoteAddr);
            
            // イベント待ち
            DWORD dwWaitResult = WaitForSingleObject (hEvent, 60000);
            if (WAIT_OBJECT_0 == dwWaitResult)
            {
                WSANETWORKEVENTS NetworkEvents;
                ZeroMemory (&NetworkEvents, sizeof NetworkEvents);
                
                // イベント内容を調べると同時にイベントをリセットする
                nRet = WSAEnumNetworkEvents (s, hEvent, &NetworkEvents);
                if (SOCKET_ERROR != nRet)
                {
                    // イベント内容はビットフラグ
                    if (FD_CONNECT & NetworkEvents.lNetworkEvents)
                    {
                        if (NetworkEvents.iErrorCode [FD_CONNECT_BIT])
                        {// エラーは配列のビット位置
                            // エラー処理(接続失敗)
                        }
                        else
                        {
                            return true;    // コネクト完了なら戻すとか
                        }
                    }
                }
            }
        }
        WSACloseEvent (hEvent);
    }
    closesocket (s);
}

まあ、connectならこんな手続きだけど、この、NetworkEvents.lNetworkEvents の特定のビットが立っていたら、そのエラーを調べるのが、「ビットフラグのビット位置」なのが、大変やりにくいとかねがね思っていた。だって、FD_CONNECT とか、FD_CONNECT_BIT の定義がこうなってるんだもん。

#define FD_CONNECT_BIT   4
#define FD_CONNECT       (1 << FD_CONNECT_BIT)

つまり、

FD_CONNECT == 2 FD_CONNECT_BIT

ってことじゃん?じゃあこんな関数が定義できるかと思って。

inline int GetNetworkErrorCode (LPWSANETWORKEVENTS lpNetworkEvents, long lNetworkEvent)
{
    // lpNetworkEvents に格納されている、lNetworkEvent に対応するエラーコードを得る
    return lpNetworkEvents->iErrorCode [log (lNetworkEvent) / log (2)];
}

ほんとかな。C言語のlog関数も自然対数なんかどうかは知りません。

トラックバック

このエントリーにトラックバック:
http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/1266

コメント

コメントする

※ コメントスパム対策のため、コメント本文はおはよう、こんにちわ、こんばんわのいずれかより始めるようにしてください。

name:
email:

※ 必要ですが、表示しません。

url:
情報を保存する ?