gpt4 book ai didi

c# - 关闭入站套接字会导致重新读取旧数据

转载 作者:行者123 更新时间:2023-12-03 12:05:46 25 4
gpt4 key购买 nike

我正在寻求有关关闭监听套接字的帮助。我的问题是,当我在Shutdown()之前调用Close()时,这两个调用之一似乎触发了对接收到的最后一个数据的套接字的虚假读取。我该如何阻止呢?

我的应用程序有两对套接字,就像FTP。一个是连接到远程服务器的客户端,另一个是监听并接受来自远程主机的第二个连接的服务器。此入站连接已连接到异步OnReceived,以处理来自远程主机的未经请求的数据。

一切正常,两个 socket 可以保持连接数天或数周。但是,如果出现问题,那么我会关闭所有内容并重新开始以使用react。在调用inboundSocket.Shutdown()inbounSocket.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
}

最佳答案

OnDataReceived中,它(从注释以及忽略EndReceive的返回值的事实出发)看起来是在对EndReceive调用inboundSocket之前正在处理缓冲区中的数据。在这种情况下,您将无法指示实际从套接字读取的字节数(如果正在关闭套接字,则字节数可能为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的返回值的事实表明您期望每个接收器返回整个缓冲区的数据值,或者返回与服务器调用时相同的字节数。 Send/ BeginSend,并非总是如此。

关于c# - 关闭入站套接字会导致重新读取旧数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15502405/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com