既存の接続がリモートホストによって強制的に閉じられました


159

メッセージとともにSocketExceptionをスローしている商用アプリケーションを使用しています。

既存の接続がリモートホストによって強制的に閉じられました

これは、クライアントとサーバー間のソケット接続で発生します。接続は正常で、データのヒープが転送されていますが、どこからともなく切断されます。

誰かこれを見たことがある?原因は何でしょうか?私はいくつかの原因を推測することができますが、原因を突き止めるためにこのコードにさらに追加する方法はありますか?

コメント/アイデアは大歓迎です。

... 最新の ...

いくつかの.NETトレースからのロギングがあります。

System.Net.Sockets Verbose: 0 : [8188] Socket#30180123::Send() DateTime=2010-04-07T20:49:48.6317500Z

System.Net.Sockets Error: 0 : [8188] Exception in the Socket#30180123::Send - An existing connection was forcibly closed by the remote host DateTime=2010-04-07T20:49:48.6317500Z 

System.Net.Sockets Verbose: 0 : [8188] Exiting Socket#30180123::Send() -> 0#0

ロギングの他の部分に基づいて、 '0#0'が長さ0バイトのパケットが送信されていることを示しているという事実を見ました。しかし、それは本当にどういう意味ですか?

2つの可能性のうちの1つが発生しています。

1)接続は閉じられていますが、データがソケットに書き込まれているため、上記の例外が発生しています。0#0は、ソケットがすでに閉じられているため、何も送信されなかったことを意味します。

2)接続はまだ開いており、0バイトのパケットが送信されています(つまり、コードにバグがあります)。0#0は、0バイトのパケットが送信されようとしていることを意味します。

何を考えていますか?それは私が推測する決定的ではないかもしれませんが、おそらく誰か他の人がこの種のものを見たことがありますか?


ただのアップデート。私たちのネットワーク設定のため、wiresharkはこの場合それをカットしないようです。しかし、うまくいけば、これを試すつもりです。blogs.msdn.com/ dgorti / archive / 2005/09/18 / 471003.aspxは、いくつかのログファイルを生成する.NETを使用してトレースしています。私はあなたを投稿し続けます...
ピーター2010

1
comcastは、偽のIDで偽装された「ゼロ」パケットを送信してp2pトラフィックを混乱させることも知られています---

回答:


98

これは通常、リモート側が(通常はTCP / IP RSTパケットを送信することによって)接続を閉じたことを意味します。サードパーティのアプリケーションを使用している場合、考えられる原因は次のとおりです。

  • 不正な形式のデータをアプリケーションに送信している(HTTPS要求をHTTPサーバーに送信することを含む可能性がある)
  • クライアントとサーバー間のネットワークリンクが何らかの理由でダウンしています
  • サードパーティ製アプリケーションで、クラッシュの原因となるバグを引き起こした
  • サードパーティアプリケーションがシステムリソースを使い果たしました

最初のケースが何が起こっているかである可能性があります。

Wiresharkを起動して、ワイヤーで何が起こっているかを正確に確認して、問題を絞り込むことができます。

より具体的な情報がなければ、ここにいる誰もがあなたを本当に助けることができるとは思えません。


2
すごい。ありがとう。ワイヤーシャークについての他のこと。それは非常に多くのデータを収集します、どうすればこのようなものをフィルタリングできますか?Wiresharkが表示された場合、後で投稿する可能性があります...
peter

4
少なくとも、WiresharkダンプをIPアドレスとポート番号でフィルタリングできるはずです。その後、ストリームの最後(問題が発生した場所)を確認し、最初に問題が発生した場所を特定できるまで逆方向に作業することは、おそらく最も役に立ちます。含まれるプロトコルの複雑さによっては、それは本当に簡単にほぼ不可能になる可能性があります...
RarrRarrRarr

4
箇条書きのソースはありますか、または以下のゲーマーの回答はリストをコピーしただけですか?
Zack

7
「不正な形式のデータを送信する」とはhttpshttpサーバーにリクエストを送信することを意味し、逆もまた同様です。
AXMIM 2017

2
私の場合、アプリをローカルで実行しているときにAPIを呼び出すときにのみ、この例外が発生していました。開発、QA、または本番環境では問題ありません。修正?ローカルでhttpsの代わりにhttpを使用します。ロードバランサーに関連している可能性があります。しかし、dev、qa、prodのweb.configsをhttpsの変換で更新しました。問題が解決しました。
カーショー2018年

82

TLS 1.2を使用してこのエラーを解決しました。
これでTLS 1.2を使用してアプリケーションを強制できます(サービスを呼び出す前に必ず実行してください):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 

別の解決策:
TLS1.2を使用するには、ローカルマシンまたはサーバーで強力な暗号化を有効にします。デフォルトでは無効になっているため、TLS1.0のみが使用されます。
強力な暗号化を有効にするには、PowerShellで管理者権限で次のコマンドを実行します。

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord 

これらの変更を有効にするには、コンピュータを再起動する必要があります。


1
複数の値を一緒に追加して、複数のプロトコルをサポートできます。したがって、SSL3からTLS1.2までのすべてをサポートするには、SecurityProtocol =(SecurityProtocolType)4080を設定します。
そろばん

29

これはコードのバグではありません。これは.Netのソケット実装からのものです。以下のように、オーバーロードされたEndReceiveの実装を使用すると、この例外は発生しません。

    SocketError errorCode;
    int nBytesRec = socket.EndReceive(ar, out errorCode);
    if (errorCode != SocketError.Success)
    {
        nBytesRec = 0;
    }

1
これは、オペレーティングシステム、最終的にはピアからのものです。それがソフトウェアのバグであるという主張のさらなる説明が必要です。
ローンの侯爵

5
+1。私のC#プログラムでEndReceiveは、クライアントが正常に終了したときに例外がスローされる理由について頭を悩ませていました。これが仕様によるものであることを知りませんでした。通常のコードフローで例外をスローするのは悪いデザインだと思います。オーバーロードされたメソッドを神に感謝します。
Pavan Manjunath、2015

2
@MSaudiこれは非同期呼び出しを使用しています。返されるデータの処理中にコードが停止しないことを確認してください。例では、msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspxを使用しています。基本的には、上記のコードを実行し、そのコードを呼び出すという、というStateObjectクラスpublic byte[] buffer = new byte[1024], public Socket socket;の関数と関数を呼び出す必要Receive(Socket s)StateObject so = new StateObject(); so.socket = s; s.BeginReceive(so.buffer, 0, 256, 0, new AsyncCallback(ReceiveCallback), so); ありvoid ReceiveCallback(IAsyncResult ar)ます。
vapcguy

2
@cagatayそれは解決策を提供しますが、何かを行うSend前に、何を実行した後に何が戻ってくるかをすぐに知る必要がある非同期メソッドに価値を見たことはありません。
vapcguy

3
実際、私はこの方法が絶対確実ではないことを発見しました。また、OPのエラーが発生する可能性があります: stackoverflow.com/questions/17790612/...
vapcguy

10

この一般的な迷惑な問題の簡単な解決策:

.context.cs」ファイル(「* .edmx」ファイルの下にある「 .context.tt」の下にあります)に移動します。

次に、この行をコンストラクタに追加します。

public DBEntities() 
        : base("name=DBEntities") 
    { 
        this.Configuration.ProxyCreationEnabled = false; // ADD THIS LINE !
    }

これがお役に立てば幸いです。


@Esiこれをどこに置く?戻り値の型はありませんか?
Khalil Khalaf

2
@FirstStep:これはコンストラクタです。
Nikhil Agrawal

3
これは、問題が発生しているエンティティフレームワークを使用しているユーザーにのみ役立ちますsocket.Send(x); byte[] buffer = new byte[1]; socket.Receive(buffer, 0, 1, 0);。OPの問題である、返されたバイトを読み取るために単純に実行しているユーザーには役立ちません。
vapcguy

ENTITY FRAMEWORKこのソリューションのみを使用するとうまくいく場合!!! これだけ!:)
ラオハマス

9

同じバグがありました。トラフィックがプロキシ(私の場合はフィドラー)を使用して送信された場合に実際に機能しました。.NETフレームワークを4.5.2から> = 4.6に更新し、すべて正常に動作するようになりました。実際のリクエストは次のとおりです
new WebClient().DownloadData("URL");
。例外は次のとおりです。

SocketException:既存の接続がリモートホストによって強制的に閉じられました


5
これは私にとって問題を解決する1つの方法でした。実際には、デフォルトで使用されるTLS .NETのバージョンに関係していました。4.5.2以前のバージョンではTLS 1.0を使用しましたが、4.6以降では1.1と1.2を許可する方が賢明です。これは、サーバーのTLS要件を1.0にドロップすることでも証明できました。これにより、問題も修正されました。
HotN

4

エンティティの循環参照のため、この例外が発生しました。

public class Catalog
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public Catalog Parent { get; set; }
    public ICollection<Catalog> ChildCatalogs { get; set; }
}

Parentプロパティに[IgnoreDataMemberAttribute]を追加しました。これで問題は解決しました。


2

.Net 4.5.2サービスで実行している場合

私にとっては、呼び出しが.Net 4.5.2サービスで実行されていたため、問題はさらに複雑になりました。@willmazの提案に従いましたが、新しいエラーが発生しました。

ロギングをオンにしてサービスを実行すると、ターゲットサイトとのハンドシェイクでokが開始され(ベアラトークンが送信されます)、Postコールを処理する次のステップで、認証トークンがドロップされ、サイトがと返信してくださいUnauthorized

サービスプールの資格情報にはTLS(?)を変更する権限がないことがわかりました。ローカルの管理者アカウントをプールに追加すると、すべて機能しました。


2

ストリームからデータを読み取っているときにこの例外が発生する場合は、これが役立つことがあります。次のようなループでHttpResponseMessageを読み取ると、この例外が発生しました。

using (var remoteStream = await response.Content.ReadAsStreamAsync())
using (var content = File.Create(DownloadPath))
{
    var buffer = new byte[1024];
    int read;

    while ((read = await remoteStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
    {
        await content.WriteAsync(buffer, 0, read);
        await content.FlushAsync();
    }
}

しばらくして、原因がバッファサイズであることがわかりました。バッファサイズが小さすぎて、弱いAzureインスタンスではうまく機能しませんでした。助けとなったのは、コードを次のように変更することです。

using (Stream remoteStream = await response.Content.ReadAsStreamAsync())
using (FileStream content = File.Create(DownloadPath))
{
    await remoteStream.CopyToAsync(content);
}

CopyTo()メソッドのデフォルトのバッファーサイズは81920です。大きなバッファーはプロセスを高速化し、エラーはすぐに停止しました。これは、全体的なダウンロード速度が向上したためと考えられます。しかし、なぜこのエラーを防ぐためにダウンロード速度が重要なのでしょうか?

ダウンロード速度がサーバーが許可するように構成されている最小しきい値を下回るため、サーバーから切断される可能性があります。たとえば、ファイルのダウンロード元のアプリケーションがIISでホストされている場合、http.sys構成に問題がある可能性があります。

「Http.sysは、IISがクライアントとのhttp通信を実行するために使用するhttpプロトコルスタックです。MinBytesPerSecondと呼ばれるタイマーがあり、転送速度が数kb /秒のしきい値を下回った場合に接続を強制終了します。デフォルトでは、このしきい値は240 kb /秒に設定します。」

この問題はTFS開発チームからのこの古いブログ投稿で説明されており、特にIISに関係していますが、正しい方向に向かっている可能性があります。また、このHTTP.sysの属性に関連した古いバグを言及:リンク

Azureアプリサービスを使用していて、バッファーサイズを増やしても問題が解決しない場合は、コンピューターもスケールアップしてみてください。接続帯域幅を含む、より多くのリソースが割り当てられます。


0

私は同じ問題を抱えていて、最終的にそれを解決することができました。私の場合、クライアントがリクエストを送信するポートには、SSL証明書がバインドされていませんでした。そこで、サーバー側のポートにSSL証明書をバインドすることで問題を修正しました。それが行われると、この例外はなくなりました。


-1

このエラーは、CIPプロトコルを使用するアプリケーションで、10秒未満でデータを送受信しなかった場合に発生しました。

これは、フォワードオープンメソッドの使用が原因でした。これを回避するには、他の方法を使用するか、転送オープン接続を維持する10秒未満の更新レートをインストールします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.