kapanışı ile ilgili sorunlar şu anda basit bir istemci sunucu sohbet programı üzerinde çalışıyorum (C# 'da istemci sunucusu iletişimine girmek istedim). Sunucudan düzgün şekilde ayrılmak dışında çok çalışır.TcpClient ve NetworkStream'in
client.Client.Disconnect(false); // client is the TcpClient
client.Close();
sunucusunda istemciden mesajlar için bekleyen bir dişli döngü vardır:
private void StartChat()
{
int requestCount = 0;
byte[] bytesFrom = new byte[10025];
string dataFromClient = null;
string rCount = null;
while (true)
{
try
{
requestCount++;
NetworkStream stream = tcpClient.GetStream();
int bufferSize = (int)tcpClient.ReceiveBufferSize;
if (bufferSize > bytesFrom.Length)
{
bufferSize = bytesFrom.Length;
}
stream.Read(bytesFrom, 0, bufferSize);
dataFromClient = System.Text.Encoding.UTF8.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
rCount = Convert.ToString(requestCount);
string message = client.Name + " says: " + dataFromClient;
program.Broadcast(message);
}
catch(Exception ex) when (ex is ObjectDisposedException || ex is InvalidOperationException || ex is System.IO.IOException)
{
program.UserDisconnected(client);
break;
}
catch(ArgumentOutOfRangeException ex)
{
Debug.WriteLine(ex.ToString());
break;
}
catch(Exception ex)
{
Debug.WriteLine(ex.ToString());
break;
}
}
istemci bağlantısını kesmeden ben bağlantıyı kapatmak için buraya Bu kodu kullanmak Ýstemcide
Yukarıda gösterilen kod ile işlev her zaman akışı almayı ve böyle bir çıktı üretmeyi sağlar:\0\0\0\0\0\0\0 [and so on]
Bu durumda $
dizin olmadığı için ArgumentOutOfRangeException
atılacak. Bu durumda $
. Döngüden kaçınmak ve bitmek için break
ekledim. Şaşırtıcı bir şekilde, ObjectDisposedException
atılmayacaktır. Ayrıca System.IO.IOException
atılmayacaktır, ancak akım kapatıldığı için bağlantı reddedilmiş olmalıdır.
Sunucuya bağlı istemci uygulamasını kapatırsam, sunucu döngüyü durdurmaz, yalnızca istemcinin bağlantısı kesildiği için gelmeyecek bir akış bekler.
İstemcinin bağlantısı kesilip kesilmediğini nasıl algılayabilirim? İstemci bağlantısını bir bağlantıyı kapatmak için uygun bir şekilde kapattığım yoldur?
Yardımlarınız için teşekkürler!
Güncelleme:
private void StartChat()
{
int requestCount = 0;
byte[] bytesFrom = new byte[10025];
string dataFromClient = null;
string rCount = null;
while (true)
{
try
{
requestCount++;
NetworkStream stream = tcpClient.GetStream();
stream.ReadTimeout = 4000;
int bufferSize = (int)tcpClient.ReceiveBufferSize;
if (bufferSize > bytesFrom.Length)
{
bufferSize = bytesFrom.Length;
}
// Wait for a client message. If no message is recieved within the ReadTimeout a IOException will be thrown
try
{
int bytesRead = stream.Read(bytesFrom, 0, bufferSize);
stream.Flush();
if (bytesRead == 0)
{
throw new System.IO.IOException("Connection seems to be refused or closed.");
}
}
catch (System.IO.IOException)
{
byte[] ping = System.Text.Encoding.UTF8.GetBytes("%");
stream.WriteTimeout = 1;
stream.Write(ping, 0, ping.Length);
continue;
}
dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
rCount = Convert.ToString(requestCount);
string message = client.Name + " says: " + dataFromClient;
program.Broadcast(message);
}
catch(Exception ex) when (ex is ObjectDisposedException || ex is InvalidOperationException || ex is System.IO.IOException)
{
Debug.WriteLine(ex.ToString());
program.UserDisconnected(client);
break;
}
catch(ArgumentOutOfRangeException ex)
{
Debug.WriteLine(ex.ToString());
}
catch(Exception ex)
{
Debug.WriteLine(ex.ToString());
break;
}
}
}
Bu, istemcinin kaybolup gitmediğini algılayamayacağınız anlamına mı geliyor? Docu'ya bakmak bir ObjectDispoedException veya en azından bir IOException atması gerektiğinden daha fazla okunamayacağı için – chris579
A _graceful_ disconnect istisnai bir durum değildir ve 'stream.Read()' döndürme 0 ile algılanır. Bir istisna eylemcisi var, ama kendiniz atmayın ve sonra kullanmaya çalıştığınız sürece ObjectDisposedException 'atılmış olduğundan şüpheleniyorum. –
Haklısınız, bu nesne hala orada olmadığı ve çöp toplayıcı tarafından silinmediği veya elden çıkarılmadığı sürece DisposedException atılmayacak. Ancak, büyük teşekkürler, bu işe yaradı! Cevabınızı en kısa zamanda kabul edeceğim. Düzenleme: İstemciyi kapatırsam, döngü sona ermez ve sunucu uygulaması kapanana kadar kalır. Bunu nasıl düzeltebilirim? – chris579