C#套接字阻塞,零数据

时间:2014-07-15 14:41:23

标签: c# sockets tcp blocking blocked

我已经实现了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 }
    }

谢谢!

2 个答案:

答案 0 :(得分:0)

<强>解决

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

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

答案 1 :(得分:0)

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