可以更有效地处理这个异步套接字吗?

本文关键字:异步 套接字 有效地 处理 | 更新日期: 2023-09-27 18:03:57

我正在接收大量消息,我想使我的ReceivedCallBack更有效。

我正在使用一些方便的字符串处理-但有一个更快的方式?

    public class StateObject
    {
        public Socket socket = null;
        public const int BufferSize = 256;
        public byte[] buffer = new byte[BufferSize];
        public StringBuilder sb = new StringBuilder();
        public string SessionID()
        {
            return socket.Handle.ToString();
        }
    }
public void ReceivedCallBack(IAsyncResult ar)
    {
        StateObject state = (StateObject)ar.AsyncState;
        Socket socket = state.socket;
        try
        {
            int bytesRead = socket.EndReceive(ar);
            if (bytesRead > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

                string[] contents = state.sb.ToString().Split('@');
                int delimCount = state.sb.ToString().Count(x => x == '@');
                for (int d = 0; d < delimCount; d++)
                {
                    if (contents[d] != "")
                        OnMessage(state, contents[d]);
                }
                if (!state.sb.ToString().EndsWith("@"))
                {
                    state.sb.Clear();
                    state.sb.Append(contents[contents.Count() - 1]);
                }
                else
                {
                    state.sb.Clear();
                }
                socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, new AsyncCallback(ReceivedCallBack), state);
            }
            else
            {
                // If no data was recieved then the connection is probably dead
                OutputWriteLine("Client " + state.SessionID() + " disconnected");
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Unusual error during Receive!");
        }
    }

可以更有效地处理这个异步套接字吗?

这里有一个基本的问题:当你处理当前的缓冲区时,你离开了没有缓冲区的套接字。内核可能会丢弃数据包,导致重试。对于高吞吐量,您应该发布多个缓冲区,并在接收完成后立即重新发布新的空缓冲区,然后再处理已完成的缓冲区。现在说到,实现使用多个缓冲区的正确处理非常困难,因为您必须跟踪发布的顺序,并且必须小心处理不完整的消息(您不能为消息的"其余"部分重新发布部分填充的缓冲区,因为已经有一个缓冲区已发布)。有关详细信息,请阅读有关高性能Windows程序的链接文章。

现在,有了代码,您就可以配置它了。从性能分析初学者指南开始。我怀疑你会找到通常的罪魁祸首。string.Split()中的分配),但我建议您衡量自己,找到瓶颈,然后才进行更改。

对于字符串处理,请阅读这篇经典文章:为什么GNU grep很快(尽管使用Boyer-Moore搜索单个@不会那么有效)。如果可能的话,考虑将协议更改为对解析更友好的协议(例如:二进制原型buff).

字符串处理确实非常低效。分配、LINQ和每条消息的二次处理成本。同样,呼叫sb.ToString 3次也无济于事。

将应用程序置于满负荷状态并分析此代码,以查看是否需要优化。如果是,您可能应该先应用一些简单的修复程序,并解决我提到的问题。

一般来说,您可能不应该编写自己的(基于ascii的)网络协议。简单地使用一些现成的东西,如WCF、HTTP或protobuf。