リスニングソケットをシャットダウンするためのサポートを探しています。私が抱えている問題は、Shutdown()
直前に呼び出したときにClose()
、これら2つの呼び出しの1つが、最後に受信したデータのソケットで偽の読み取りをトリガーしているように見えることです。どうすれば止められますか?
私のアプリには、FTPのように2組のソケットがあります。1つはリモートサーバーに接続するクライアントであり、もう1つはリモートホストからの2番目の接続をリッスンして受け入れるサーバーです。このインバウンド接続は非同期に接続されOnReceived
、リモートホストからダウンする一方的なデータを処理します。
これはすべて正常に機能し、両方のソケットを数日または数週間接続したままにすることができます。しかし、何か問題が発生した場合は、すべてをシャットダウンしてやり直すことで対応します。inboundSocket.Shutdown()
またはinbounSocket.Close()
(どちらが2番目のスレッドでデバッグするのが難しいかわからない)の呼び出し中に、インバウンドソケットの最後のインバウンドパケットを再読み取りしているように見えます。これにより、さらに多くの問題が発生します。
どうすればシャットダウンできますか。この再読み取りを強制せずに、閉じる、切断するなど?
以下のサンプルコードは、要点を示すために削除されています。
前もって感謝します。
ダニエル
public class TcpIpSenderReceiver
{
/// <summary>
/// Main thread, main entry point
/// </summary>
public void ConnectAndLogonAndStartReceivingInboundMessages()
{
CreateListenerAndStartListening();
AcceptInboundSocketAndHookUpDataReceiptCallBack();
}
/// <summary>
/// Main thread
/// </summary>
int CreateListenerAndStartListening()
{
tcpListener = new TcpListener(LocalBoundIpAddress, listeningPort);
tcpListener.Start();
}
/// <summary>
/// SECOND thread
/// </summary>
void AcceptInboundSocketAndHookUpDataReceiptCallBack()
{
int i = 0;
while (i < 100 && !tcpListener.Pending())
{
i++;
Thread.Sleep(100);
}
inboundSocket = tcpListener.AcceptSocket();
bufferForReceive = new byte[bufferSize];
WireUpCallbackForAsynchReceive();
}
/// <summary>
/// SECOND thread
/// </summary>
void WireUpCallbackForAsynchReceive()
{
if (asynchCallbackFunctionForReceive == null)
{
asynchCallbackFunctionForReceive = new AsyncCallback(OnDataReceived);
}
if (inboundSocket.Connected)
{
try
{
asyncResultForReceive = inboundSocket.BeginReceive(bufferForReceive, 0, bufferForReceive.Length, SocketFlags.None, asynchCallbackFunctionForReceive, null);
}
catch (Exception)
{
//...
}
}
}
/// <summary>
/// SECOND thread
/// </summary>
void OnDataReceived(IAsyncResult asyn)
{
// Read data call goes here.....
if (asyncResultForReceive != null)
{
inboundSocket.EndReceive(asyncResultForReceive);
}
WireUpCallbackForAsynchReceive(); // listen again for next inbound message
}
void Shutdown()
{
shouldAbortThread = true;
asyncResultForReceive = null;
asynchCallbackFunctionForReceive = null;
if (outboundStreamWriter != null)
{
try
{
outboundStreamWriter.Close();
outboundStreamWriter.Dispose();
outboundStreamWriter = null;
}
finally { }
}
if (outboundNetworkStream != null)
{
try
{
outboundNetworkStream.Close();
outboundNetworkStream.Dispose();
outboundNetworkStream = null;
}
finally { }
}
if (tcpClient != null)
{
try
{
tcpClient.Close();
tcpClient = null;
}
catch (SocketException)
{
// ...
}
}
if (inboundSocket != null)
{
try
{
// I think this is where it's puking
inboundSocket.Shutdown(SocketShutdown.Both);
inboundSocket.Close();
inboundSocket = null;
}
catch (SocketException)
{
//...
}
}
if (tcpListener != null)
{
try
{
tcpListener.Stop();
tcpListener = null;
}
catch (SocketException)
{
//...
}
}
}
#region Local variables
volatile bool shouldAbortThread;
TcpListener tcpListener;
TcpClient tcpClient;
StreamWriter outboundStreamWriter;
NetworkStream outboundNetworkStream;
Socket inboundSocket = null;
IAsyncResult asyncResultForReceive;
public AsyncCallback asynchCallbackFunctionForReceive;
byte[] bufferForReceive;
static string HostnameShared;
#endregion
}