关闭TCP套接字 - 调试器关闭连接时有什么不同

时间:2014-06-18 08:46:20

标签: c# .net sockets

我创建了一个到PLC的套接字连接:

IPEndPoint endPoint = new IPEndPoint(plcAddress, PORT);
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_socket.Connect(endPoint);

m_stream = new NetworkStream(m_socket);
m_writer = new StreamWriter(m_stream);
m_reader = new StreamReader(m_stream);

当我关闭程序或用户点击退出时,我会调用此代码:

if (m_reader != null) m_reader.Close();
if (m_writer != null) m_writer.Close();
if (m_stream != null) m_stream.Close();
if (m_socket != null)
{
    m_socket.Shutdown(SocketShutdown.Both);
    m_socket.Disconnect(false);
    m_socket.Close();
    m_socket.Dispose();
    m_socket = null;
}

但PLC没有意识到连接已关闭。我无法更改PLC上的任何代码。

但是当我在连接处于活动状态时停止VisualStudio调试器(Shift + F5)时,它会正确关闭。什么是VisualStudio以不同的方式做什么?

修改

当我通过Shift + F5

停止程序时,这两行由wireshark捕获

enter image description here

编辑2:

我有一个读取数据的线程:

while (m_runListener)
{
    int cnt = m_reader.Read(buffer, 0, 1024);
    if (cnt > 0)
    {
        // handle data
    }
}

当我关闭程序时,我无法在不调用Thread.Abort();的情况下停止该程序 如果我删除阻止呼叫m_reader.Read(buffer, 0, 1024);仅用于测试,则断开连接工作。

2 个答案:

答案 0 :(得分:0)

我最近遇到了一个非常类似的问题,我也发现通过Visual Studio进行调试也使问题消失了。我相信这是因为Visual Studio中的调试器需要额外的时间来处理事务,加上断点显然会阻止您在结束代码中执行的代码执行。

我讨厌的工作是在一些结束代码之间调用Thread.Sleep(xxxx)。我在ShutdownDisconnect调用之后有一个允许这些进程完成。我尝试了不同的值,但我确定了100毫秒,因为这确保问题再也不会发生。

显然,更好的方法是看看你是否可以将这些调用放入异步方法中,并且只在第一次完成时调用下一个调用,但由于项目规模较小而没有使用它,我没有打扰会得到。

然而,我可能完全错了,这不是你所遇到的问题,它听起来与我几周前的问题非常相似。

答案 1 :(得分:0)

我终于在这里找到了解决问题的方法:
http://sysperf.yingyuhsieh.com/2007/08/force-tcp-closed-by-sending-rst-c.html

通常,TCP连接关闭如下:

  1. 客户端将FIN发送到服务器,服务器以ACK
  2. 响应
  3. 服务器向客户端发送FIN,客户端以ACK
  4. 响应

    在我的情况下,第二步失踪了。

    我需要强制发送RST数据包。这可以通过以下代码完成:

    m_socket.Send(new byte[1]);
    m_socket.Shutdown(SocketShutdown.Receive);