gpt4 book ai didi

sockets - C# TCP 服务器/客户端对象传输/序列化/反序列化越来越多地使用内存帮助需要

转载 作者:可可西里 更新时间:2023-11-01 02:54:27 27 4
gpt4 key购买 nike

首先,

提前感谢所有可能提供帮助、批评和建议的人。

语言:C#


目标:用于图像和对象传输的 TCP 服务器/客户端。


服务器场景:服务器将监听客户端连接。

客户端连接后,服务器将从套接字接收byte[]数据

Server会将byte[]转换成(Type)object。

然后服务器将使用此(类型)对象来更新 WPF 图像控件


客户端场景:

客户端将创建准备传输的对象。

客户端会将对象转换为存储的字节[]。

客户端将连接到服务器并通过套接字发送对象


问题:

我不确定为什么这个进程每秒增加 60-100MB 的内存使用量。

我想知道 Byte[] 分 block 是否是一个值得的解决方案(如果是的话,请给我指点资源或提供解决方案)

感觉它没有正确清理自身或重新使用变量。


注意事项:

Bitmap Capture and Convert to Byte[] 运行良好据我所知这不是问题,但如果问题不在下面的代码中或者其他人会受益,我可以发布代码。

ObjecttoByte[] 和 ByteArrayToObject 代码有效,并从其他堆栈溢出帖子中略微修改,如果问题不在下面的代码中或者其他人会受益,那么我可以发布它。


服务器监听器代码:

public void StartServer()
{
//-------------------------------------------------------
// Initialize Variables For Server
//-------------------------------------------------------
int recv;
byte[] data;

//-------------------------------------------------------
// Configure Server Listener
//-------------------------------------------------------
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//-------------------------------------------------------
// Bind Socket To IPEndpoint And Listen
//-------------------------------------------------------
newsock.Bind(ipep);
newsock.Listen(10);

//-------------------------------------------------------
// Accept New Connection
//-------------------------------------------------------
Console.WriteLine("Waiting for a client...");
Socket client = newsock.Accept();

//-------------------------------------------------------
// Verify Client Endpoint Connection
//-------------------------------------------------------
IPEndPoint clientep = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}", clientep.Address, clientep.Port);

//-------------------------------------------------------
// Start Reading From Socket While Client Connected
//-------------------------------------------------------
while (client.Connected)
{
data = new byte[500000]; // Create Buffer For Object

recv = client.Receive(data); // Ensure Client Has Sent Data
if (recv == 0)
break;

//-------------------------------------------------------
// Create Test Object And De-Serialize
//-------------------------------------------------------
TestObject to = new TestObject(); //Object For Storage
Console.WriteLine("Server Object Size: " + data.Length); // Check Length For Interest

var dataToObject = ByteArrayToObject(data); // Convert Object Byte[] to Object
to = (TestObject)dataToObject; // Store Converted Byte[] Object into Typed Object

Console.WriteLine("Server De-Serialized Object from Client."); // Provide Information
Console.Out.WriteLine("Server TestObject: " + to.testString); // Extract And Notify Object String Data

//-------------------------------------------------------
// Update Main GUI Image (WPF)
//-------------------------------------------------------
this.Dispatcher.Invoke((Action)(() =>
{
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap)); // Create Type Converter
Bitmap bitmap1 = (Bitmap)tc.ConvertFrom(to.testBmp); // Cast into Bitmap from Byte[]
imgRemoteDisplay.Source = ByteMonImaging.GetBitmapSource(bitmap1); // Display Bitmap
bitmap1 = null;
tc = null;
}));

//-------------------------------------------------------
// Clean Up
//-------------------------------------------------------
dataToObject = null;
data = null;
to = null;
GC.Collect();
//-------------------------------------------------------
}

Console.WriteLine("Disconnected from {0}", clientep.Address);

//-------------------------------------------------------
// Close Listener
//-------------------------------------------------------
client.Close();
newsock.Close();
}

客户端连接代码:

public void ConnectClient()
{
//-------------------------------------------------------
// Configure Server Connection
//-------------------------------------------------------
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//-------------------------------------------------------
// Establish Connection To Server
//-------------------------------------------------------
try
{
server.Connect(ipep);
}
catch (SocketException e)
{
Console.WriteLine("Unable to connect to server.");
Console.WriteLine(e.ToString());
return;
}

//-------------------------------------------------------
// Start Sending Object To Server While Connected
//-------------------------------------------------------
while(server.Connected)
{
TestObject to = new TestObject(); // Create blank object store

to.testString = "TestObject String Here"; // Set Blank Object Test String
var bmpToSend = ByteMonImaging.CaptureBitmap(); // Set Blank Object Test Bitmap
to.testBmp = ByteMonImaging.ImageToByte(bmpToSend); // Convert Bitmap to Byte[]

var byteArray = ObjectToByteArray(to); // Pack Object into Byte[]
Console.WriteLine("Client Object Size: " + byteArray.Length); // Curious Byte[] Size
server.Send(byteArray); // Send Byte[] Object Via TCP
Console.WriteLine("Client Sent Serialized Object to Server."); // Notify Where We Are At

bmpToSend = null; // Clean Up
to = null; // Clean Up
byteArray = null; // Clean Up
GC.Collect(); // Clean Up (Added for Checks)
}

//-------------------------------------------------------
// Close Connection to Socket And Server
//-------------------------------------------------------
Console.WriteLine("Disconnecting from server...");
server.Shutdown(SocketShutdown.Both);
server.Close();
}

内存消耗原因定位

//-------------------------------------------------------
// Update Main GUI Image (WPF)
//-------------------------------------------------------
this.Dispatcher.Invoke((Action)(() =>
{
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap)); // Create Type Converter
Bitmap bitmap1 = (Bitmap)tc.ConvertFrom(to.testBmp); // Cast into Bitmap from Byte[]
imgRemoteDisplay.Source = ByteMonImaging.GetBitmapSource(bitmap1); // Display Bitmap
bitmap1 = null;
tc = null;
}));

解决方案: 问题是 hBitmap 在调用时导致内存泄漏。使用 finally 子句,我能够使用 externdll 删除对象。

 [DllImport("gdi32")]
static extern int DeleteObject(IntPtr ipObj);
public static BitmapSource GetBitmapSource(Bitmap bmp)
{
IntPtr hBitmap = bmp.GetHbitmap();
System.Windows.Media.Imaging.BitmapSource b;
try
{
b = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
System.Windows.Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
}
finally
{
DeleteObject(hBitmap);
}
return b;
}

最佳答案

解决方案: 问题是 hBitmap 在调用时导致内存泄漏。使用 finally 子句,我能够使用 externdll 删除对象。

 [DllImport("gdi32")]
static extern int DeleteObject(IntPtr ipObj);

public static BitmapSource GetBitmapSource(Bitmap bmp)
{
IntPtr hBitmap = bmp.GetHbitmap();
System.Windows.Media.Imaging.BitmapSource b;
try
{
b = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
System.Windows.Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
}
finally
{
DeleteObject(hBitmap);
}
return b;
}

关于sockets - C# TCP 服务器/客户端对象传输/序列化/反序列化越来越多地使用内存帮助需要,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26985782/

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