C# 减少网络带宽使用
C# Reducing the Network bandwith usage
我会做一个简短的介绍:我在用 c# 开发一个小屏幕共享项目,我使用 Tcp Protocol
发送数据。基本上我从 GDI 调用 BitBlt
方法,它工作得很好。第一次我发送整个缓冲区,然后我迭代并仅发送更改的像素。
我发送的缓冲区中的每个字节都代表一个组件(在 Rgba 顺序中)- 这是一个简短示例的小数组:
byte[] pixelarray = { 45, 201, 173,1 };
//R=45,G=201,B=173,Alpha=1(always 1 on screen).
让我们继续前进。
我的屏幕是 1920x1080(在我的例子中)所以实际上 1920x1080x4(每个像素是 4 个字节)= 最多 8,294,400 个像素。
使用 Gzipstream
compressiong 将大小减少到 ~250kb。这是我在第一个 time.After 中发送的内容,我只是比较每个 BitBlt
捕获的字节数组并仅发送发生变化的像素。看起来像这样:
public void StartAsync(ScreenFrame frame)
{
using (var memoryStream = new MemoryStream())
{
for (var i = 0; i < frame.NewPixels.Length; i += 4)
{
memoryStream.WriteByte(frame.NewPixels[i]);
memoryStream.WriteByte(frame.NewPixels[i + 1]);
memoryStream.WriteByte(frame.NewPixels[i + 2]);
}
byte[] data = compress(memoryStream.ToArray());//compress gzip.
SendVarData(data);//this is a simple function to send it on a socket.
}
}
public void DeltaAsync(ScreenFrame frame)
{
using (var memoryStream = new MemoryStream())
{
for (var i = 0; i < frame.NewPixels.Length; i += 4)//loop through buffers and write only differnt bytes.
{
if (frame.NewPixels[i] == frame.PreviousPixels[i] &&
frame.NewPixels[i + 1] == frame.PreviousPixels[i + 1] &&
frame.NewPixels[i + 2] == frame.PreviousPixels[i + 2])
continue;
memoryStream.Write(BitConverter.GetBytes(i), 0, 4);//write the index.
memoryStream.WriteByte(frame.NewPixels[i]);
memoryStream.WriteByte(frame.NewPixels[i + 1]);
memoryStream.WriteByte(frame.NewPixels[i + 2]);
}
byte[] buff = compress(memoryStream.ToArray());//compress gzip.
SendVarData(buff);
}
}
在另一端处理和应用更改不是我的主要问题。
我真正的瓶颈是带宽使用。桌面上的一个小变化,例如当用户使用鼠标右键单击并打开经典菜单时,发送的数据是(压缩后!)大约120~150kb!
我真的很想优化它。当只有很小的变化时,我不能让我的程序通过网络发送大量数据......
如您所见,我已经在使用
gzip 压缩(提供高压缩比)。
只写差异。
我正在寻找优化网络想法的方法...我非常感谢任何收到的帮助,因为我很长时间都在努力思考一些可以帮助的事情...
谢谢。
对屏幕的更改通常会影响矩形块中的所有(或大部分)字节。您的压缩效率低下(与其他远程查看器应用程序相比),因为它没有考虑到这一点。一种方法是尝试识别已更改区域的边界,然后发送使用 png 等压缩的整个区域。但实际上,您应该研究 png 的变换类型和其他图像压缩算法对二维数据执行的操作,以使它们更易于压缩。
变换是对图像数据的可逆操作,在数据压缩步骤之前应用,旨在使数据更易于压缩。一种变换可能是从上一行中的像素中减去像素值。如果图像从一行到下一行变化不大,你会从中得到很多零,这将比每行的实际像素数据更可压缩。
我会做一个简短的介绍:我在用 c# 开发一个小屏幕共享项目,我使用 Tcp Protocol
发送数据。基本上我从 GDI 调用 BitBlt
方法,它工作得很好。第一次我发送整个缓冲区,然后我迭代并仅发送更改的像素。
我发送的缓冲区中的每个字节都代表一个组件(在 Rgba 顺序中)- 这是一个简短示例的小数组:
byte[] pixelarray = { 45, 201, 173,1 };
//R=45,G=201,B=173,Alpha=1(always 1 on screen).
让我们继续前进。
我的屏幕是 1920x1080(在我的例子中)所以实际上 1920x1080x4(每个像素是 4 个字节)= 最多 8,294,400 个像素。
使用 Gzipstream
compressiong 将大小减少到 ~250kb。这是我在第一个 time.After 中发送的内容,我只是比较每个 BitBlt
捕获的字节数组并仅发送发生变化的像素。看起来像这样:
public void StartAsync(ScreenFrame frame)
{
using (var memoryStream = new MemoryStream())
{
for (var i = 0; i < frame.NewPixels.Length; i += 4)
{
memoryStream.WriteByte(frame.NewPixels[i]);
memoryStream.WriteByte(frame.NewPixels[i + 1]);
memoryStream.WriteByte(frame.NewPixels[i + 2]);
}
byte[] data = compress(memoryStream.ToArray());//compress gzip.
SendVarData(data);//this is a simple function to send it on a socket.
}
}
public void DeltaAsync(ScreenFrame frame)
{
using (var memoryStream = new MemoryStream())
{
for (var i = 0; i < frame.NewPixels.Length; i += 4)//loop through buffers and write only differnt bytes.
{
if (frame.NewPixels[i] == frame.PreviousPixels[i] &&
frame.NewPixels[i + 1] == frame.PreviousPixels[i + 1] &&
frame.NewPixels[i + 2] == frame.PreviousPixels[i + 2])
continue;
memoryStream.Write(BitConverter.GetBytes(i), 0, 4);//write the index.
memoryStream.WriteByte(frame.NewPixels[i]);
memoryStream.WriteByte(frame.NewPixels[i + 1]);
memoryStream.WriteByte(frame.NewPixels[i + 2]);
}
byte[] buff = compress(memoryStream.ToArray());//compress gzip.
SendVarData(buff);
}
}
在另一端处理和应用更改不是我的主要问题。 我真正的瓶颈是带宽使用。桌面上的一个小变化,例如当用户使用鼠标右键单击并打开经典菜单时,发送的数据是(压缩后!)大约120~150kb! 我真的很想优化它。当只有很小的变化时,我不能让我的程序通过网络发送大量数据...... 如您所见,我已经在使用
gzip 压缩(提供高压缩比)。
只写差异。
我正在寻找优化网络想法的方法...我非常感谢任何收到的帮助,因为我很长时间都在努力思考一些可以帮助的事情...
谢谢。
对屏幕的更改通常会影响矩形块中的所有(或大部分)字节。您的压缩效率低下(与其他远程查看器应用程序相比),因为它没有考虑到这一点。一种方法是尝试识别已更改区域的边界,然后发送使用 png 等压缩的整个区域。但实际上,您应该研究 png 的变换类型和其他图像压缩算法对二维数据执行的操作,以使它们更易于压缩。
变换是对图像数据的可逆操作,在数据压缩步骤之前应用,旨在使数据更易于压缩。一种变换可能是从上一行中的像素中减去像素值。如果图像从一行到下一行变化不大,你会从中得到很多零,这将比每行的实际像素数据更可压缩。