.NET Async Server无缘无故地接收数据

时间:2011-08-11 04:18:40

标签: c# .net sockets

我现在完全糊涂了。

编辑:好的,没关系。 Python套接字现在也开始这样做了。

编辑2:嗯,不太确定这是否会导致高CPU使用率,但随机的是。有没有一种有效的方法来找出导致使用量激增的原因?这个项目有点大,有各种各样的线程。

我有一个异步服务器,它监听并等待传入​​连接,然后使它们保持活动状态并等待套接字刷新并提供服务器数据。它仅在用户想要关闭套接字时关闭。

然而,每当我让一个插座&流保持连接,它开始变得混乱并开始在无限循环中发送空数据...它可能需要15秒到超过一分钟才能开始变坏。如果我让它真的真的很长时间,它会开始导致非常高的CPU使用率。

除了高CPU使用率,奇怪的是,一切都按预期工作;消息发送&收到罚款。

这是我的回读函数:

    protected void ReadCallback(IAsyncResult ar)
    {
        StateObject state = (StateObject)ar.AsyncState;
        Socket handler = state.SocketHandle;

        try
        {
            int bytesRead = (state.BytesRead += handler.EndReceive(ar)), offset = 0;
            string line = m_Encoder.GetString(state.Buffer, 0, bytesRead);
            if ( state.Buddy != null )
                Console.WriteLine(state.Buddy.Address);
            if (bytesRead > 0)
            {
                Console.WriteLine("!!!");
                /* A complete request? */
                if (line.EndsWith("\n") || line.EndsWith("\x00"))
                {
                    string[] lines = line.Split('\n'); // ... *facepalm*
                    foreach (string ln in lines)
                        this.MessageReceieved(ln, state);

                    state.Buffer = new byte[StateObject.BUFFER_SIZE];
                    state.BytesRead = 0; // reset
                }
                /* Incomplete; resize the array to accommodate more data... */
                else
                {
                    offset = bytesRead;
                    Array.Resize<byte>(ref state.Buffer, bytesRead + StateObject.BUFFER_SIZE);
                }
            }
            if (handler != null && handler.Connected )
                handler.BeginReceive(state.Buffer, offset, state.Buffer.Length - offset, SocketFlags.None, new AsyncCallback(ReadCallback), state);

        }
        catch (SocketException)
        {
            if (state.Buddy != null)
                state.Buddy.Kill();
            else
                handler.Close();
        }
    }

我知道这是通过调用BeginReceive以某种方式引起的,但我不知道如何保持连接活着。

1 个答案:

答案 0 :(得分:2)

该代码中没有任何内容可以使它变得混乱。

我确实看到了一些问题。

连接检测

无需检查插座是否已连接。您可以在接收回调中以两种方式检测断开连接:

  1. EndReceive
  2. 返回零字节
  3. 正在抛出异常。
  4. 我建议你在EndReceive之后做的第一件事是检查返回值并相应地处理断开连接。它使代码更清晰。

    如果收到0个字节,您的代码将无法执行任何操作。 handler将停止接收并仍然认为连接已打开。

    缓冲区处理

    你的缓冲区处理非常有效。不要每次调整缓冲区大小。它会降低你的服务器速度。从开始分配大缓冲区。

    字符串处理

    每次收到某些内容时都不要构建字符串。在新行之后检查字节缓冲区内部或者替换为null。然后构建一个字符串,只根据需要使它变大。您可能会收到更多仅包含消息的字节(例如,一条半消息)