【问题标题】:C# socket blocking with zero data零数据的 C# 套接字阻塞
【发布时间】:2014-07-17 23:32:48
【问题描述】:

我已经实现了 C# tcp-ip 客户端(同步和异步读取套接字)。 在每个 SocketException 之后,我会自动重新连接与服务器的连接。

然后我在windows中测试了客户端与ncat的通信。在这里,如果我杀死 ncat,它会在 C# 客户端中抛出 SocketException,并且一切正常。

但后来我在 linux 中使用 ncat 对其进行了测试 - 这里通信正常,但如果我杀死 ncat 服务器(与 Windows 相同的设置 - ncat -l -k -p xxxx),回调中接收到大量空数据(零B)(或在同步版本中等待套接字)并且没有抛出异常。

一件事是 Windows / Unix 版本的 ncat 可以有不同的行为。但我仍然需要为任何版本的 tcp-ip 服务器解决这种奇怪的行为。

    /* ------------------------------------------------------------------------- */
    public void WaitForData()
    {
        try
        {
            if (callback == null)
                callback = new AsyncCallback(OnDataReceived);

            SocketPacket packet = new SocketPacket();
            packet.thisSocket = socket;

            m_result = socket.BeginReceive
                (packet.dataBuffer, 0, 256,
                SocketFlags.None, callback, packet);
        }
        catch (SocketException ex) { ///reconnecting }
    }

    /* ------------------------------------------------------------------------- */
    public class SocketPacket
    {
        public System.Net.Sockets.Socket thisSocket;
        public byte[] dataBuffer = new byte[256];
    }

    /* ------------------------------------------------------------------------- */
    public void OnDataReceived(IAsyncResult asyn)
    {
        try
        {
            SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
            int iRx = theSockId.thisSocket.EndReceive(asyn);
            char[] chars = new char[iRx];
            System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
            int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
            string szData = new string(chars);
            szData = szData.Replace("\n", String.Empty);

            processMessage(szData);

            WaitForData();
        }

        catch (ObjectDisposedException) { }
        catch (SocketException ex) { ///reconnecting }
    }

谢谢!

【问题讨论】:

  • 通常情况下,客户端向死掉的服务器进程发送数据会导致 FIN 或 RST 被发回,从而关闭连接。但是,如果服务器突然终止或网络断开连接,并且客户端没有尝试发送任何内容,它很容易挂起等待数据。你应该让你的客户对这些问题有弹性。 (超时、定期保活等...)我建议您发布您的代码,以便我们了解客户端的行为。
  • 问题是,我不知道如何检查它是否还活着,因为一切似乎都已连接但服务器已关闭。

标签: c# sockets tcp blocking blocked


【解决方案1】:

已解决

在 OnDataReceived 回调中,我检查传入数据的数量,所以我这样做了:

if (iRx == 0)
   throw new SocketException(Convert.ToInt16(SocketError.HostDown));

【讨论】:

    【解决方案2】:

    TCP 接收器永远无法获得远程连接的确切状态。根据 TCP/IP 堆栈实现,终止进程将发送 FIN(接收为零)或 RST(获取异常)。还有其他情况,应用程序完全不知道连接中断。假设如果远程系统被强制重置或者电缆线被拔掉或者IP地址被改变,在你发送一些数据之前你是无法知道连接断开的。如果您的应用程序需要知道连接的状态,它可以每 1 分钟发送一些虚拟数据以确保连接处于活动状态。

    【讨论】:

    • 是的,我尝试在这种情况下发送数据,并且也毫无例外地被处理。我通过检测传入数据是否不为零来解决它,无论如何我都会抛出异常。但我想这只是一种解决方案......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-20
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多