サーバーアプリがあり、クライアントが接続しようとすると、次のエラーが表示されることがあります。
注:「クライアントからストリームを取得できなかったか、ログインに失敗しました」は、catchステートメントで追加されたテキストです
停止する行(sThread:行96)は次のとおりです。
tcpClient = (TcpClient)client;
clientStream = tcpClient.GetStream();
sr = new StreamReader(clientStream);
sw = new StreamWriter(clientStream);
// line 96:
a = sr.ReadLine();
この問題の原因は何ですか?常に発生するわけではないことに注意してください
通常、このエラーは、ターゲットマシンが実行されているが、接続しようとしているサービスが利用できないことを意味します。 (停止、クラッシュ、または別の要求でビジー状態です。)
英語:machine(サービスが実行されるリモートホスト/サーバー/ PC)への接続は行われましたが、サービスが利用できなかったため- onそのマシン、マシンはリクエストの処理方法を知りませんでした。
マシンへの接続が利用できない場合、別のエラーが表示されます。私はそれが何であるかを忘れますが、それは「サービス到達不能」または「利用不可」の線に沿っています。
編集-追加
ISこれは、ポートをブロックしているファイアウォールが原因である可能性がありますが、断続的である(「クライアントが接続しようとするとき」)と言う場合は、ほとんどありません。私は返信する前に精神的にそれを排除していたので、私は元々それを含めなかった。
Webサービスを呼び出すときにこのエラーを受け取りました。この問題は、トランスポートレベルのセキュリティにも関連していました。 Webサイトプロジェクトを介してWebサービスを呼び出すこともできますが、テストプロジェクトで同じコードを再利用すると、このメッセージを含むWebExceptionが発生します。呼び出しを行う前に次の行を追加すると、問題が解決しました。
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
編集
System.Net.ServicePointManager.SecurityProtocol -このプロパティは、Secure Sockets Layer(SSL)またはTransport Layer Securityのバージョンを選択します(HTTPS)スキームのみを使用する新しい接続に使用する(TLS)プロトコル。既存の接続は変更されません。
プロトコルバージョンを選択する際のTLSハンドシェイク中にSecurityProtocol
構成が重要であると思います。
TLSハンドシェイク -このプロトコルは、実際のアプリケーションデータの交換のために両側で必要なすべての情報を交換するために使用されますTLS。
ClientHello-クライアントは、サポートする最高のTLSプロトコルバージョンを指定してClientHelloメッセージを送信します...
ServerHello-サーバーは、選択されたプロトコルバージョンを含むServerHelloメッセージで応答します...選択されたプロトコルバージョンは、クライアントとサーバーの両方で最も高い必要がありますサポート。たとえば、クライアントがTLSバージョン1.1をサポートし、サーバーがバージョン1.2をサポートする場合、バージョン1.1を選択する必要があります。バージョン1.2は選択しないでください。
私の具体的なケースシナリオは、Azureアプリサービスの最小TLSバージョンが1.2に変更されたことです。
これがデフォルトかどうかはわかりませんが、1.0に戻すと機能しました。
「SSL設定」内の設定にアクセスできます。
これらのブログ投稿のどの修正が助けになったかはわかりませんが、そのうちの1つがこの問題を私のためにソートしました...
私を助けたトリックは、WebRequestの使用をやめて、代わりにHttpWebRequestを使用することでした。 HttpWebRequestにより、3つの重要な設定で遊ぶことができます:
そして
サーバーの1つからのHTTPSサービスへの呼び出しも、「トランスポート接続からデータを読み取れません:既存の接続が強制的に閉じられました」例外をスローしていました。ただし、HTTPサービスは正常に機能しました。 Wiresharkを使用して、TLSハンドシェイクの失敗であることを確認しました。結局、サーバー上の暗号スイートを更新する必要があるということになりました。
これは断続的な問題には役立ちませんが、同様の問題を抱えている他の人には役立つかもしれません。
VMを複製し、新しいIPアドレスを使用して別のネットワークで起動しましたが、IISのバインドは変更しませんでした。 Fiddlerが「トランスポート接続からデータを読み取れません:既存の接続がリモートホストによって強制的に閉じられました」と表示され、IEが「TLS 1.0、TLS 1.1、およびTLS 1.2をAdvancedで有効にする」と言っていました設定"。バインディングを新しいIPアドレスに変更することで解決しました。
何らかの理由で、サーバーへの接続が失われました。サーバーが明示的に接続を閉じたか、サーバーのバグが原因で予期せず閉じられた可能性があります。または、クライアントとサーバー(スイッチまたはルーター)の間の何かが接続を切断しました。
問題を引き起こしたのはサーバーコードかもしれませんし、そうでないかもしれません。サーバーコードにアクセスできる場合は、そこにデバッグを配置して、クライアント接続が閉じられたときに通知できます。これにより、接続が切断されるタイミングと理由が示される場合があります。
クライアントでは、サーバーがいつでも失敗する可能性を考慮してコードを記述する必要があります。それはまさにその方法です。ネットワーク接続は本質的に信頼できません。
これで私の問題が解決しました。リクエストが行われる前に次の行を追加しました。
System.Net.ServicePointManager.Expect100Continue = false;
100継続動作をサポートしていないサーバーの方法でプロキシがあったようです。
私は過去にその問題を抱えています。 PostgreSQLを使用しています。プログラムを実行すると、接続したり、そのようなエラーがスローされることがあります。
コードを試すとき、パブリックフォームの下の一番最初の行に接続コードを配置します。以下に例を示します。
前:
public Form1()
{
//HERE LIES SOME CODES FOR RESIZING MY CONTROLS DURING RUNTIME
//CODE
//CODE AGAIN
//ANOTHER CODE
//CODE NA NAMAN
//CODE PA RIN!
//Connect to Database to generate auto number
NpgsqlConnection iConnect = new NpgsqlConnection("Server=localhost;Port=5432;User ID=postgres;Password=pass;Database=DB");
iConnect.Open();
NpgsqlCommand iQuery = new NpgsqlCommand("Select * from table1", iConnect);
NpgsqlDataReader iRead = iQuery.ExecuteReader();
NpgsqlDataAdapter iAdapter = new NpgsqlDataAdapter(iQuery);
DataSet iDataSet = new DataSet();
iAdapter.Fill(iDataSet, "ID");
MessageBox.Show(iDataSet.Tables["ID"].Rows.Count.ToString());
}
今:
public Form1()
{
//Connect to Database to generate auto number
NpgsqlConnection iConnect = new NpgsqlConnection("Server=localhost;Port=5432;User ID=postgres;Password=pass;Database=DB");
iConnect.Open();
NpgsqlCommand iQuery = new NpgsqlCommand("Select * from table1", iConnect);
NpgsqlDataReader iRead = iQuery.ExecuteReader();
NpgsqlDataAdapter iAdapter = new NpgsqlDataAdapter(iQuery);
DataSet iDataSet = new DataSet();
iAdapter.Fill(iDataSet, "ID");
MessageBox.Show(iDataSet.Tables["ID"].Rows.Count.ToString());
//HERE LIES SOME CODES FOR RESIZING MY CONTROLS DURING RUNTIME
//CODE
//CODE AGAIN
//ANOTHER CODE
//CODE NA NAMAN
//CODE PA RIN!
}
私は、プログラムが何かを行う前に最初に接続を読み取らなければならないと思います。しかし、私の研究によると、それはコードの問題ではなく、実際にはマシン自体からのものでした。
ハッピーコーディング!
System.Net.ServicePointManager.Expect100Continue = false;
この問題は、プロキシサーバーがWebサーバーに実装されているために発生する場合があります。送信サービスを呼び出す前にこの行を配置してプロキシサーバーをバイパスするには。
最初にハンドシェイクを確立できるかどうかを確認してください。以前にファイルをアップロードするときにこの問題が発生しましたが、アップロードを削除してパラメーターを指定してログインできるかどうかを確認したときに、問題が存在しないルートであることがわかりました。
送信されたリクエストを試してみるために、サードパーティアプリケーション(Fiddler)を実行していました。このアプリケーションを閉じると修正されました
クライアントのWebサイトがWeb APIサービスに接続しようとして同じメッセージを取得するという非常に類似した問題がありました。これは、IISが実行されていたサーバーでコードの変更やWindowsの更新がなかったときに、完全に突然発生し始めました。
私たちの場合、呼び出し元のWebサイトはTLS 1.0のみをサポートするバージョンの.Netを使用しており、何らかの理由でIISが実行されていたサーバーがTLS 1.0呼び出しの受け入れを停止したようです。これを診断するには、IISのサーバー上のレジストリを介してTLSを明示的に有効にしてから、そのサーバーを再起動する必要がありました。これらはregキーです:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.0\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.0\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.1\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.1\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.2\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.2\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001
If that doesn't do it, you could also experiment with adding the entry for SSL 2.0:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001
ここの別の質問 に対する私の答えには、エントリを追加するために使用したこのpowershellスクリプトがあります:
注:古いセキュリティプロトコルを有効にすることはお勧めできません。この場合の正しい答えは、TLS 1.2を使用するためにクライアントWebサイトのコードを更新することです。 、ただし、上記のレジストリエントリは、そもそも問題の診断に役立ちます。
ドメインにhttps証明書がある場合は、IISのドメイン名にhttpsバインディングがあることを確認してください。 IIS->ドメインを選択-> [バインディング]をクリックします[サイトバインディング]ウィンドウが開きます。 httpsのバインディングを追加します。
同様の問題があり、使用したアプリとファイアウォール/ロードバランサーをバイパスしたかどうかに応じて次のエラーが発生していました:
[blah]へのHTTPSハンドシェイク(#136の場合)が失敗しました。 System.IO.IOExceptionトランスポート接続からデータを読み取れません:既存の接続がリモートホストによって強制的に閉じられました
そして
ReadResponse()failed:サーバーはこのリクエストに対して完全なレスポンスを返しませんでした。サーバーは0バイトを返しました。
問題は、SSLサーバー証明書が失われ、いくつかのサーバーにインストールされていないことでした。
これが私に起こった理由は、DIプロバイダーに再帰的な依存関係があったからです。私の場合、私は持っていました:
services.AddScoped(provider => new CfDbContext(builder.Options));
services.AddScoped(provider => provider.GetService<CfDbContext>());
修正は、2番目のスコープサービス登録を削除するだけでした。
services.AddScoped(provider => new CfDbContext(builder.Options));