gpt4 book ai didi

C# TCP 套接字性能随着应用程序运行而下降

转载 作者:太空狗 更新时间:2023-10-30 01:08:09 25 4
gpt4 key购买 nike

我编写了一个 C# 服务器应用程序。服务器使用异步 TCP 套接字。

数据包是 80-180 字节的数据。

为了性能测试,我有一个客户端连接并连续发送数据包。调试前 100 个数据包 (0-100) 在大约 5 秒内接收。当服务器接收到数据包 #300-400 时,接收数据包大约需要 30 秒。随着更多的接收发生,性能继续下降。

我环顾四周,未能找到解决方案。我已经尝试设置 Socket.NoDelay 标志以防 Nagle 算法抑制服务器。

我已禁用服务器内的所有功能;所以它只是接收以确保我不会在其他代码中失去性能。

我还检查了我的 CPU 使用率,大约是 13%。我有超过 2 GB 的可用内存。运行应用程序时,内存不会不断增长,利用率也很低。

我对接下来要调试和研究的内容一头雾水......

编辑:添加代码示例

public void StartListening()
{

try
{
IPAddress ipAddress = IPAddress.Parse("192.168.2.60");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, m_Port);
m_MainSocket = new Socket(localEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
m_MainSocket.NoDelay = true;
m_MainSocket.Bind(localEndPoint);
m_MainSocket.Listen(10);
m_MainSocket.BeginAccept(new AsyncCallback(clientConnected), null);

System.Diagnostics.Debug.WriteLine("Listening on:Local IP Address: " + localEndPoint.Address.ToString() + " Port :" + localEndPoint.Port.ToString() + "\n");
}
catch (SocketException se)
{
System.Diagnostics.Debug.WriteLine("Listening Exception \n");
System.Diagnostics.Debug.WriteLine(se.Message);
}
}

void clientConnected(IAsyncResult ar)
{
try
{
SocketState state = new SocketState(m_MainSocket.EndAccept(ar));
Client client = new Client(state);

if (client.SocketState.clientSocket.Connected)
{
System.Diagnostics.Debug.WriteLine("Client #?????? Connected \n");
AddLogText("Client #?????? Connected \r\n\r\n");
waitForData(client);
SetSendButton(true);
}

m_MainSocket.BeginAccept(new AsyncCallback(clientConnected), null);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debug.WriteLine("Client Connected: Socket has been closed\n");
}
catch (SocketException se)
{
System.Diagnostics.Debug.WriteLine("Client Connected Exception \n");
System.Diagnostics.Debug.WriteLine(se.Message);
}
}

void waitForData(Client client)
{
try
{
SocketState state = new SocketState(client.SocketState.clientSocket);
client.SocketState.clientSocket = null;
client.SocketState = state;
client.SocketState.clientSocket.BeginReceive(client.SocketState.DataBuffer, 0, client.SocketState.DataBuffer.Length, SocketFlags.None, new AsyncCallback(readDataCallback), client);
}
catch (SocketException se)
{
System.Diagnostics.Debug.WriteLine("Wait For Data Exception \n");
System.Diagnostics.Debug.WriteLine(se.Message);
}

}

public void readDataCallback(IAsyncResult ar)
{
Client client = (Client)ar.AsyncState;
try
{
// Read data from the client socket.
int iRx = client.SocketState.clientSocket.EndReceive(ar);
client.SocketState.SB.Append(Encoding.ASCII.GetString(client.SocketState.DataBuffer, 0, iRx));
string sPacketString = client.SocketState.SB.ToString();

Server formServer = this;
Packet_Helper packet_helper = new Packet_Helper(sPacketString, formServer);

Packet packet = new Packet(sPacketString);
client.SerialNumber = packet.SerialNumber;
client.FirmwareVersion = packet.FirmwareVersion;
client.ProductID = packet.ProductID;
client.HardwareVersion = packet.HardwareVersion;
if (!m_Clients.ContainsKey(packet.SerialNumber))
{
m_Clients.Add(packet.SerialNumber, client);
UpdateClientList();
string[] packets = client.refreshAll();
for (int i = 0; i < packets.Length; i++)
{
byte[] byteData = Encoding.ASCII.GetBytes(packets[i]);
client.SocketState.clientSocket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
AddPacketsSentText(packets[i] + "--" + (iSent++).ToString() + "\r\n\r\n");
}
}

System.Diagnostics.Debug.WriteLine("Read " + sPacketString.Length.ToString() + " bytes from " + client.SerialNumber + "\n" + sPacketString + "\n");
AddLogText("Read " + sPacketString.Length.ToString() + " bytes from " + client.SerialNumber + " \r\n");
AddLogText(sPacketString.ToString() + "\r\n\r\n");

waitForData(client);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
}
catch (SocketException se)
{
if (se.ErrorCode == 10054) // Error code for Connection reset by peer
{
string sclientSerial = "??????";
if (client.SerialNumber != null || client.SerialNumber != "")
sclientSerial = client.SerialNumber;
AddLogText("Client " + sclientSerial + " Disconnected" + "\r\n\r\n");
System.Diagnostics.Debug.WriteLine("Client " + sclientSerial + " Disconnected" + "\n");

m_Clients.Remove(sclientSerial);
UpdateClientList();
}
else
{
System.Diagnostics.Debug.WriteLine("Read Data Exception \n");
System.Diagnostics.Debug.WriteLine(se.Message);
}
}
}


class SocketState
{
private Socket m_ClientSocket; //Socket connection to the client
private byte[] m_DataBuffer = new byte[256]; //Buffer to store the data sent by the client
private StringBuilder m_SB = new StringBuilder(); //for building recieved data into a string

/// <summary>
/// Gets or Sets the client Socket
/// </summary>
public Socket clientSocket
{
get { return m_ClientSocket; }
set { m_ClientSocket = value; }
}

/// <summary>
/// Gets the DataBuffer
/// </summary>
public byte[] DataBuffer
{
get { return m_DataBuffer; }
set { DataBuffer = value; }
}

/// <summary>
/// Gets or Sets the SB
/// </summary>
public StringBuilder SB
{
get { return m_SB; }
set { m_SB = value; }
}

public SocketState(Socket socket)
{
m_ClientSocket = socket;
m_ClientSocket.ReceiveBufferSize = 256;
m_ClientSocket.NoDelay = true;
//m_DataBuffer = Enumerable.Repeat((byte)0, 256).ToArray();
}
}

编辑:添加了 AddLogText() 函数。此函数用于将文本添加到 UI 中的文本框。

//Delegate - 启用异步调用以设置 tb_ListeningLog 的文本属性

delegate void AddLogTextCallback(string text);

private void AddLogText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.tb_ListeningLog.InvokeRequired)
{
AddLogTextCallback d = new AddLogTextCallback(AddLogText);
this.Invoke(d, new object[] { text });
}
else
{
this.tb_ListeningLog.Text += text;
tb_ListeningLog.SelectionStart = tb_ListeningLog.Text.Length;
tb_ListeningLog.ScrollToCaret();
}
}

最佳答案

我对这个答案有点摸不着头脑,但您发布的代码肯定有帮助。

随着时间的推移,您可能会看到性能下降的原因是 readDataCallback 方法中的代码。按照您设置的方式,数据处理是在您进行另一次接收之前完成的。这意味着随着处理时间的增加,接收数据之间的持续时间也会增加。

我不知道您的许多方法中的代码是什么,但您通常应该查看可能需要一段时间才能完成的任何循环。如果您无法通过查看代码找到瓶颈,请尝试找出完成时间最长的方法并继续缩小代码范围。

例如(我猜瓶颈在这部分代码中):

if (!m_Clients.ContainsKey(packet.SerialNumber))
{
m_Clients.Add(packet.SerialNumber, client);

AddLogText("Running UpdateClientList\r\n");

UpdateClientList();

AddLogText("Doing client.refreshAll\r\n");

string[] packets = client.refreshAll();

AddLogText("Doing for loop\r\n");

for (int i = 0; i < packets.Length; i++)
{
byte[] byteData = Encoding.ASCII.GetBytes(packets[i]);
client.SocketState.clientSocket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
AddPacketsSentText(packets[i] + "--" + (iSent++).ToString() + "\r\n\r\n");
}
}

只需用眼睛观察每种方法之间的时间量,或者使用 StopwatchDateTime 来显示准确的时间。

此外,如果您发现代码的行为无法提高效率,您可以尝试在单独的线程中处理数据。不过,由于手头的问题,我假设这种行为是不需要的。


对于您的 AddLogText 方法,请尝试使用 tb_ListeningLog.Text.AppendText 而不是 +=。

关于C# TCP 套接字性能随着应用程序运行而下降,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10342526/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com