我遇到了这个严重的问题。
我有异步TcpListener。有时有几个连接的客户端,一切都很好。有时即使有一个人。服务器开始使用我CPU的50-60%。
我认为问题可能在于处理读取异常,但这是我的唯一提示,我不知道如何测试它。
以下是服务器的代码:
class Server
{
private TcpListener server;
public Server(string hostname, int port = 25000)
{
server = new TcpListener(IPAddress.Parse(hostname), port);
}
public void ServerStart()
{
server.Start();
WaitForClientConnect();
}
private async void WaitForClientConnect()
{
TcpClient client = await server.AcceptTcpClientAsync();
Console.WriteLine("The async connection created for: " + ((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());
OnClientConnect(client);
}
private void OnClientConnect(TcpClient client)
{
ClientLowAPI clientReq = new ClientLowAPI(client);
WaitForClientConnect();
}
}
以下是处理单个客户端的代码:
class ClientLowAPI
{
private TcpClient client;
private NetworkStream stream;
public ClientLowAPI(TcpClient clientConnected)
{
client = clientConnected;
stream = client.GetStream();
WaitForHeader();
}
private async void WaitForHeader()
{
byte[] buffer = new byte[4];
int bytesRead = 0;
while (bytesRead < 4)
{
try
{
bytesRead += await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead);
}
catch
{
stream.Close();
client.Close();
return;
}
}
WaitForData(FourBytesToInt(buffer));
}
private async void WaitForData(int length)
{
byte[] buffer = new byte[length];
int bytesRead = 0;
while (bytesRead < length)
{
try
{
bytesRead += await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead);
}
catch
{
stream.Close();
client.Close();
return;
}
}
ExecuteMessage(buffer);
}
private void ExecuteMessage(byte[] binaryData)
{
// Do something with message
WaitForHeader();
}
public async void SendMessage(byte[] message)
{
byte[] buffer = new byte[message.Length + 4];
byte[] length = IntToFourBytes(message.Length);
length.CopyTo(buffer, 0);
message.CopyTo(buffer, 4);
try
{
await stream.WriteAsync(buffer, 0, buffer.Length);
}
catch
{
stream.Close();
client.Close();
return;
}
}
private int FourBytesToInt(byte[] array)
{
int res = 0;
res += array[0] * 256 * 256 * 256;
res += array[1] * 256 * 256;
res += array[2] * 256;
res += array[3];
return res;
}
private byte[] IntToFourBytes(int intValue)
{
byte[] array = new byte[4];
array[0] = (byte)(intValue >> 24);
array[1] = (byte)(intValue >> 16);
array[2] = (byte)(intValue >> 8);
array[3] = (byte)intValue;
return array;
}
}
答案 0 :(得分:1)
问题是由这个循环引起的:
while (bytesRead < 4)
{
try
{
bytesRead += await stream.ReadAsync(buffer, bytesRead, buffer.Length - bytesRead);
}
catch
{
stream.Close();
client.Close();
return;
}
}
通常是强制连接被杀死,服务器引发了异常,但有时客户端通过TcpClient.Close()正确关闭了连接,然后没有引发异常,并且stream.ReadAsync方法启动返回0,这导致了巨大的无限循环CPU使用率。
对于快速修复,我使用以下条件:
if (bytesRead == 0)
{
throw new System.IO.IOException();
}