C# 关闭入站套接字导致重新读取旧数据
我正在寻找关闭监听插座的帮助。我遇到的问题是,当我在C# 关闭入站套接字导致重新读取旧数据,c#,sockets,shutdown,C#,Sockets,Shutdown,我正在寻找关闭监听插座的帮助。我遇到的问题是,当我在Close()之前调用Shutdown()时,这两个调用中的一个似乎会在套接字上触发对最后接收到的数据的虚假读取。我怎么才能停止呢 我的应用程序有两对套接字,很像FTP。一个是连接到远程服务器的客户端,另一个是侦听并接受来自远程主机的第二个连接的服务器。此入站连接连接连接到异步OnReceived,以处理来自远程主机的未经请求的数据 这一切工作正常,两个插座可以保持连接数天或数周。但如果出了问题,我会关闭一切,然后重新开始。在调用inbound
Close()
之前调用Shutdown()
时,这两个调用中的一个似乎会在套接字上触发对最后接收到的数据的虚假读取。我怎么才能停止呢
我的应用程序有两对套接字,很像FTP。一个是连接到远程服务器的客户端,另一个是侦听并接受来自远程主机的第二个连接的服务器。此入站连接连接连接到异步OnReceived
,以处理来自远程主机的未经请求的数据
这一切工作正常,两个插座可以保持连接数天或数周。但如果出了问题,我会关闭一切,然后重新开始。在调用inboundSocket.Shutdown()
或inboundSocket.Close()
(不确定是哪个,很难在第二个线程中调试)的过程中,就好像我正在重新读取入站套接字上的最后一个inboudn数据包。这将导致更多的问题
我怎样才能关机。在不强制重新读取的情况下关闭、断开等
下面的示例代码,将其剥离以显示其本质
提前谢谢
丹尼尔
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
}
公共类TcpIpSenderReceiver
{
///
///主线程,主入口点
///
public void ConnectAndLogon和StartReceivingInboundMessages()
{
CreateListenerAndStartListening();
AcceptInboundSocketAndHookUpdateReceiptCallback();
}
///
///主线
///
int CreateListenerAndStartListening()
{
tcpListener=新的tcpListener(LocalBoundIpAddress,listeningPort);
tcpListener.Start();
}
///
///第二线
///
void AcceptInBoundSocketAndHookUpdateReceiptCallback()
{
int i=0;
而(i<100&!tcpListener.Pending())
{
i++;
睡眠(100);
}
inboundSocket=tcpListener.AcceptSocket();
bufferForReceive=新字节[bufferSize];
WireUpCallbackForAsynchReceive();
}
///
///第二线
///
void WireUpCallbackForAsynchReceive()
{
if(asynchCallbackFunctionForReceive==null)
{
asynchCallbackFunctionForReceive=新的AsyncCallback(OnDataReceived);
}
if(inboundSocket.Connected)
{
尝试
{
asyncResultForReceive=inboundSocket.BeginReceive(bufferForReceive,0,bufferForReceive.Length,SocketFlags.None,asynchCallbackFunctionForReceive,null);
}
捕获(例外)
{
//...
}
}
}
///
///第二线
///
收到无效数据(IAsyncResult asyn)
{
//读取数据调用转到此处。。。。。
if(asyncResultForReceive!=null)
{
EndReceive(asyncResultForReceive);
}
WireUpCallbackForAsynchReceive();//再次侦听下一条入站消息
}
无效关机()
{
shouldAbortThread=true;
asyncResultForReceive=null;
asynchCallbackFunctionForReceive=null;
if(outboundStreamWriter!=null)
{
尝试
{
outboundStreamWriter.Close();
outboundStreamWriter.Dispose();
outboundStreamWriter=null;
}
最后{}
}
if(outboundNetworkStream!=null)
{
尝试
{
outboundNetworkStream.Close();
outboundNetworkStream.Dispose();
outboundNetworkStream=null;
}
最后{}
}
if(tcpClient!=null)
{
尝试
{
tcpClient.Close();
tcpClient=null;
}
捕获(SocketException)
{
// ...
}
}
if(inboundSocket!=null)
{
尝试
{
//我想这就是它呕吐的地方
inboundSocket.Shutdown(SocketShutdown.Both);
inboundSocket.Close();
inboundSocket=null;
}
捕获(SocketException)
{
//...
}
}
if(tcpListener!=null)
{
尝试
{
tcpListener.Stop();
tcpListener=null;
}
捕获(SocketException)
{
//...
}
}
}
#区域局部变量
volatile bool应该中止线程;
TcpListener TcpListener;
TCP客户机TCP客户机;
StreamWriter超出范围StreamWriter;
NetworkStream outboundNetworkStream;
Socket-inboundSocket=null;
IAsyncResult asyncResultForReceive;
公共异步回调asynchCallbackFunctionForReceive;
字节[]用于接收;
静态字符串HostnameShared;
#端区
}
在OnDataReceived
中,您在调用inboundSocket
上的EndReceive
之前,似乎正在处理缓冲区中的数据(从注释和忽略EndReceive
)。如果是这种情况,您没有指示实际从套接字读取的字节数(如果套接字关闭,则很可能为0),因此您正在处理上一次读取的数据,因此出现了重新读取旧数据的情况
在尝试处理任何数据之前,您需要调用EndReceive
。比如:
void OnDataReceived(IAsyncResult asyn)
{
var bytesRead = inboundSocket.EndReceive(asyn);
if (bytesRead == 0) return; // Socket is closed
// Process the data here
WireUpCallbackForAsynchReceive(); // listen again for next inbound message
}
此外,您没有检查EndReceive
的返回值这一事实表明,您希望每个接收返回整个缓冲区的值
Thread dataReceivedWorkerThread;
void AcceptInboundSocketAndStartWorkerThread()
{
inboundSocket = tcpListener.AcceptSocket();
dataReceivedWorkerThread = new Thread(new ThreadStart(ListenForAndWaitToReceiveInboundData));
dataReceivedWorkerThread.Start();
}
void ListenForAndWaitToReceiveInboundData()
{
var bytesRead = 0;
try
{
bytesRead = inboundSocket.Receive(bufferForReceive, 0, bufferForReceive.Length, SocketFlags.None); // blocks here
}
catch (SocketException se)
{
if (se.SocketErrorCode == SocketError.Interrupted)
{
// Handle shutdown by (e.g.) parent thread....
}
else
{
// handle other
}
return;
}
if (bytesRead == 0)
{
// handle shutdown from other end
return;
}
// Do stuff with received data....
}
}