2

コールバックが必要なため、非同期呼び出しを使用しないことを選択します。AsynはWindows環境用に特別に作成されているため、 Unixに似たノンブロッキングソケットメソッドPoll()を使用してこれを解決する方法があるかどうかだけ知りたいです。 。これが非同期なしで実行できるかどうかを調査しています。

注意すべき点:ノンブロッキング!=非同期:)

したがって、socket&Poll()メソッドのブロッキングフラグをオフにすることで、次のアプローチがあります。

    try
    {
        IPEndPoint hostEp = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);
        Socket hostSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        hostSock.Blocking = false;
        hostSock.Connect(hostEp);

    }
    catch (Win32Exception se)
    {
        if (ex.ErrorCode == 10035) // WSAEWOULDBLOCK is expected, means connect is in progress
        while (true)
        {
            Console.WriteLine("Connecting in progress");
            bool connected = hostSock.Poll(1000000, SelectMode.SelectWrite);
            if (connected)
            {
                Console.WriteLine("Connected");
                break;
            }

        }
    }

しかし、SelectMode.SelectWriteは、接続の試行を再開しないようです。だから問題は何ですか?そして、どうすればこれを解決できますか?Poll()の代わりにSelect()を使用する必要がありますか?

4

4 に答える 4

3

非同期メソッド(ConnectAsync())を使用するだけです。これらはこのためのものです。プログラムロジックに例外を使用しないでください。

Connect()以下をブロックせずにTCPソケットを同期的に実行できます。

マニュアル

Connectを呼び出す前にBlockingプロパティをfalseに特に設定しない限り、Connectメソッドはブロックします。TCPのようなコネクション型プロトコルを使用していて、ブロッキングを無効にすると、接続に時間がかかるため、ConnectはSocketExceptionをスローします。

SocketException.ErrorCodeを使用して、特定のエラーコードを取得できます。このコードを入手した後、エラーの詳細な説明については、MSDNライブラリのWindowsSocketsバージョン2APIエラーコードのドキュメントを参照してください。

エラーがWSAEWOULDBLOCKを返した場合、リモートホスト接続はコネクション型ソケットによって開始されていますが、まだ正常に完了していません。Pollメソッドを使用して、ソケットの接続がいつ終了するかを判別します。

しかし、それはまさにあなたのコードが行うことなので、それはうまくいくはずです。

于 2012-08-23T07:46:44.963 に答える
1

メインスレッドをブロックせずにConnectを起動するために、スレッドまたはタスクを使用できます。

クロススレッド保護により、UI(WinForms / WPF)との対話が必要な場合、これにより複雑さが増します。

また、 BackgroundWorkerを使用してこの問題を回避することもできます。

于 2012-08-23T08:04:46.927 に答える
1

実際、あなたのコードは私のシステムで機能しています。ただし、もちろん、TCP接続を受け入れるサーバーが必要です。あなたがそれを持っていないなら、あなたは永遠に待つでしょう。だから私はあなたがサーバーを逃していると思います。

于 2016-01-31T22:12:57.937 に答える
1

私は正確な質問をしましたが、私にとっては答えはかなりばかげていました:私のコードには文字列(マイクロソフトから)からIpAddressをフェッチするためのストックコードがありました:

 var ipHostInfo = Dns.GetHostEntry(hostname);
 return ipHostInfo.AddressList[0];

これはすべて良かったのですが、私のテストは「127.0.0.1:9000」に対してテストしていました。これは、何らかの理由で実際のイーサネット接続のIPアドレスを認識していました。解析メカニズムを次のように変更します。

if (hostname.Equals("localhost"))
{
    return IPAddress.Parse("127.0.0.1");
}
try
{
    return IPAddress.Parse(hostname);
}
catch (FormatException e)
{
    var ipHostInfo = Dns.GetHostEntry(hostname);
    return ipHostInfo.AddressList[0];
}

トリックをしました(少なくとも私にとっては!)

于 2020-04-16T17:51:19.937 に答える