1

WinSock を使用して、特定のローカル ネットワーク カードからソケットを開く必要がありました。私はこれについて尋ね、ここで答えを得ました。つまり、最初にローカル インターフェイスにバインドしてから、connect を呼び出すことをお勧めします。

ただし、これを行うと、WSAEADDRNOTAVAIL (10049)「要求されたアドレスはそのコンテキストでは無効です。」が表示されます。どうしてこれなの?

以下のサンプル コードは、ローカル ボックス 192.168.1.3 で実行されているアプリケーションの一部であり、リモート サーバー 192.168.1.4 に接続しようとしていると仮定します。ローカル アドレスとリモート アドレスが正しいことを再確認しました。両方の方法で ping を実行できます (ローカルからリモートへ、およびリモートからローカルへ)。

ローカル用に 0 以外のポートを試しました。変わりはない。接続前にバインドを削除すると動作しますが、ネットワーク インターフェイスを指定できません。

それで、なぜ私は WSAEADDRNOTAVAIL を取得し続けるのですか?

addrinfo localhints = {0};
localhints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
localhints.ai_family = AF_INET;
localhints.ai_socktype = SOCK_STREAM;
localhints.ai_protocol = IPPROTO_TCP;

addrinfo *localaddr = NULL;
getaddrinfo("192.168.1.3", "0", &localhints, &localaddr);
bind(s, localaddr->ai_addr, localaddr->ai_addrlen);
freeaddrinfo(localaddr);

addrinfo remotehints = {0};
remotehints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
remotehints.ai_family = AF_INET;
remotehints.ai_socktype = SOCK_STREAM;
remotehints.ai_protocol = IPPROTO_TCP;

addrinfo *remoteaddr = NULL;
getaddrinfo("192.168.1.4", "12345", &remotehints, &remoteaddr);
connect(s, remoteaddr->ai_addr, remoteaddr->ai_addrlen);
freeaddrinfo(remoteaddr);

EDIT : このサンプル コードでは意図的にエラー チェックが行われていないため、最も効率的な方法で意図を伝えることができます。

編集 2 : 192.168.1.3 へのバインドにより、接続が失敗します。127.0.0.1 へのバインドは機能します。はい、192.168.1.3 が正しいローカル IP であることは 100% 確信しています。

編集3:そうです!気まぐれに、自宅の PC でテスト アプリを試してみたところ、問題なく動作しました。したがって、少なくともコードは機能し、問題は私の仕事用 PC に関連しているに違いありません。

4

2 に答える 2

1

OK、@claptrap が正しかったことがわかりました。

私はファイアウォールを無効にしていましたが、私には知られていませんでしたが、IT 部門にはエンタープライズ ウイルス スキャナーに緊密に統合された他のファイアウォール関連のものがありました (これはアンインストールまたは無効化できません)。IT に一時的に無効にしてもらうと、すべてが期待どおりに機能しました。

于 2013-02-18T21:00:00.693 に答える
0

API 関数を呼び出すときは、常にエラー コードを確認してください。

addrinfo localhints = {0};
localhints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
localhints.ai_family = AF_INET;
localhints.ai_socktype = SOCK_STREAM;
localhints.ai_protocol = IPPROTO_TCP;

addrinfo *localaddr = NULL;
int ret = getaddrinfo("192.168.1.3", "0", &localhints, &localaddr);
if (ret == 0)
{
    ret = bind(s, localaddr->ai_addr, localaddr->ai_addrlen);
    freeaddrinfo(localaddr);

    if (ret == 0)
    {
        addrinfo remotehints = {0};
        remotehints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
        remotehints.ai_family = AF_INET;
        remotehints.ai_socktype = SOCK_STREAM;
        remotehints.ai_protocol = IPPROTO_TCP;

        addrinfo *remoteaddr = NULL;
        ret = getaddrinfo("192.168.1.4", "12345", &remotehints, &remoteaddr);
        if (ret == 0)
        {
            ret = connect(s, remoteaddr->ai_addr, remoteaddr->ai_addrlen);
            freeaddrinfo(remoteaddr);

            if (ret == 0)
            {
                // connect succeeded...

                // can use getsockname() here to discover which port was actually bound to, if needed.
                // On some OS versions, bind() does not perform the actual binding immediately,
                // connect() does the actual binding instead since it can make more informed choices based on the target address being connected to...
            }
            else
            {
                // connect failed...
            }
        }
        else
        {
            // getaddrinfo() failed
        }
    }
    else
    {
        // bind failed
    }
}
else
{
    // getaddrinfo() failed...
}

コードは実際にどこまで到達しますか?

于 2013-02-12T11:04:22.440 に答える