简体   繁体   English

TCP服务器高CPU使用率

[英]TCP Server high CPU usage

C# Visual Studio 2013 C#Visual Studio 2013年

I'm working on a rough TCP Server/Client. 我正在使用粗糙的TCP Server / Client。 It works like this: 它是这样的:
Client sends message to server > Server sends "response" to client. 客户端向服务器发送消息>服务器向客户端发送“响应”。 I have this in a loop as I'm going to use this transfer of data for multiplayer in a game. 我要循环使用此数据,因为我要在游戏中将这种数据传输用于多人游戏。 However, I ran a performance test because my TCP Server was using a lot of my CPU when more than three clients connected. 但是,我进行了性能测试,因为当连接了三个以上的客户端时,我的TCP Server正在使用大量的CPU。 The performance profiler said the following method was responsible for 96% utilization. 性能分析器表示,以下方法可导致96%的利用率。 Can you help me fix this? 你能帮我解决这个问题吗?

private static void ReceiveCallback(IAsyncResult AR)
    {
        Socket current = (Socket)AR.AsyncState;
        int received;

        try
        {
            received = current.EndReceive(AR);
        }
        catch (SocketException)
        {
            Console.WriteLine("Client forcefully disconnected");
            current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway
            _clientSockets.Remove(current);
            return;
        }

        byte[] recBuf = new byte[received];
        Array.Copy(_buffer, recBuf, received);
        string text = Encoding.ASCII.GetString(recBuf);
        Console.WriteLine("Received Text: " + text);


        string msg = "Response!";
        byte[] data = Encoding.ASCII.GetBytes(msg);
        current.Send(data);


        current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
    }

Just in case, here's the AcceptCallback method which calls the ReceiveCallback. 以防万一,这是调用ReceiveCallback的AcceptCallback方法。

private static void AcceptCallback(IAsyncResult AR)
    {
        Socket socket;

        try
        {
            socket = _serverSocket.EndAccept(AR);
        }
        catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
        {
            return;
        }

        _clientSockets.Add(socket);
        socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
        Console.WriteLine("Client connected...");
        _serverSocket.BeginAccept(AcceptCallback, null);
    } 

In the comments you say that your code sends data as fast as CPU and network allow but you want to throttle it. 在注释中,您说您的代码发送数据的速度与CPU和网络允许的速度一样快,但是您希望限制它。 You probably should think about what the optimal frequency is that you want to send at. 您可能应该考虑要发送的最佳频率。 Then, send at that frequency. 然后,以该频率发送。

var delay = TimeSpan.FromMilliseconds(50);
while (true) {
 await Task.Delay(delay);
 await SendMessageAsync(mySocket, someData);
 await ReceiveReplyAsync(mySocket);
}

Note, that I have made use of await to untangle the callback mess. 注意,我已经使用了await来整理回调混乱。 If you now add timers or delays into the mix callbacks can get unwieldy. 如果现在将计时器或延迟添加到混合回调中,可能会变得笨拙。 You can do it any way you like, though. 您可以按照自己喜欢的任何方式进行操作。 Or, you simply use synchronous socket IO on a background thread/task. 或者,您仅在后台线程/任务上使用同步套接字IO。 That is even simpler and the preferred way if there aren't too many threads. 如果没有太多线程,那将是更简单和首选的方式。 Note, that MSDN usually uses the APM pattern with sockets for no good reason. 请注意,MSDN通常没有充分的理由将APM模式与套接字一起使用。

Note, that Thread.Sleep/Task.Delay are totally fine to use if you want to wait based on time. 请注意,如果要基于时间等待,则完全可以使用Thread.Sleep / Task.Delay。

Why are you doing this : 你为什么做这个 :

byte[] recBuf = new byte[received];
Array.Copy(_buffer, recBuf, received);
string text = Encoding.ASCII.GetString(recBuf);

You have a copy operation that copies your received buffer in recBuf, and then another one to create the string. 您有一个复制操作,它将收到的缓冲区复制到recBuf中,然后再复制一个以创建字符串。 You can avoid one and your performance will improve. 您可以避免一个,您的性能将会提高。 But the fact that cpu is high is normal because even tranforming to the string will make use of the cpu. 但是cpu高的事实是正常的,因为即使转换为字符串也会使用cpu。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM