【问题标题】:RFB/VNC Receiving FrameBuffer and Byte Data issue C#RFB/VNC 接收 FrameBuffer 和字节数据问题 C#
【发布时间】:2011-10-27 01:00:52
【问题描述】:

希望对 RFB 协议有经验的人能给我一个答案。

按照 RFB 协议,我实现了一个 3.3 客户端,握手,一切都很好。我不明白/遇到问题的是使用原始数据的 FrameUpdateRequest 和 FrameUpdate。

我已经逐字阅读并实施了来自 http://www.realvnc.com/docs/rfbproto.pdf 的文档 @ 内容 6.4.3 和 6.5.1

这有点乱,因为我一直在玩左、右和中心。但这是我正在做的:

public int beginNormalOperation()
{        
byte[] fbUp = new byte[10];                    

fbUp[0] = 0003; //Message type, 3= FrameBufferUpdate
fbUp[1] = 0001; //Incremental 0=true, 1=false
fbUp[2] = 0000; //X Position High Byte
fbUp[3] = 0000; //X Position Low Byte
fbUp[4] = 0000; //Y Position High Byte
fbUp[5] = 0000; //Y Position Low Byte

fbUp[6] = INTtoU16(serverSetWidth)[0];
fbUp[7] = INTtoU16(serverSetWidth)[1];
fbUp[8] = INTtoU16(serverSetHeight)[0];
fbUp[9] = INTtoU16(serverSetHeight)[1];

//fbUp[6] = 0000;
//fbUp[7] = 100;
//fbUp[8] = 0000;
//fbUp[9] = 100;   

sock.Send(fbUp);

System.Drawing.Image img;

byte[] bufferInfo = new byte[4];

try
{
sock.Receive(bufferInfo);
textBox4.AppendText("\r\n" + Encoding.Default.GetString(bufferInfo));
}
catch (SocketException ex) { MessageBox.Show("" + ex); }         

return U16toINT(bufferInfo[2], bufferInfo[3]);                     
}

返回值是矩形的个数,因为我是从按钮点击调用这个方法,然后传递给:

public void drawImage(int numRectangles)
{
 //Now within the class
//int xPos = 0;
//int yPos = 0;
//int fWidth = 0;
//int fHeight = 0;

if (myBmp == null)
{
myBmp = new Bitmap(serverSetWidth, serverSetHeight); //I'm requesting full size, so using server bounds atm
}


for (int i = 0; i < numRectangles; i++)
{
byte[] bufferData = new byte[12];
int headerLen = 0;

if (!gotRectangleHeader)
{
try
{
sock.Receive(bufferData);
}
catch (SocketException ex) { MessageBox.Show("" + ex); }

xPos = U16toINT(bufferData[0], bufferData[1]);
yPos = U16toINT(bufferData[2], bufferData[3]);
fWidth = U16toINT(bufferData[4], bufferData[5]);
fHeight = U16toINT(bufferData[6], bufferData[7]);

//headerLen = 12; //I'm now reading the first 12 bytes first so no need for this

gotRectangleHeader = true;
}

bufferData = new byte[((fWidth * fHeight)*4)];


try
{                                            
sock.Receive(bufferData);
}
catch (SocketException ex) { MessageBox.Show("" + ex); }

//Testing to see where the actual data is ending
//byte[] end = new byte[1000];

//Array.Copy(bufferData, 16125, end, 0, 1000);

//for(int f=0; f<bufferData.Length;f++)
//{
//    if (Convert.ToInt32(bufferData[f].ToString()) == 0 &&
//       Convert.ToInt32(bufferData[f + 1].ToString()) == 0 &&
//       Convert.ToInt32(bufferData[f + 2].ToString()) == 0 &&
//       Convert.ToInt32(bufferData[f + 3].ToString()) == 0)
//    {

//        Array.Copy(bufferData, f-30, end, 0, 500);
//        int o = 1;
//    }
//}

int curRow = 0;
int curCol = 0;

for (int curBit = 0; curBit < (bufferData.Length - headerLen) / 4; curBit++)
{
int caret = (curBit * 4) + headerLen;

if (curRow == 200)
{
int ss = 4;
}

Color pixCol = System.Drawing.Color.FromArgb(Convert.ToInt32(bufferData[caret+3].ToString()), Convert.ToInt32(bufferData[caret+2].ToString()), Convert.ToInt32(bufferData[caret+1].ToString()), Convert.ToInt32(bufferData[caret].ToString()));


myBmp.SetPixel(curCol, curRow, pixCol);

if (curCol == (fWidth - 1))
{
curRow++;
curCol = 0;
}
else
{
curCol++;
}

}
}

imgForm.Show();
imgForm.updateImg(myBmp);

}

我很抱歉代码,我经历了这么多排列弄乱它已经变得一团糟。

这就是我正在尝试做的事情,也是我认为它应该按照协议工作的方式:

  1. 我请求 FrameBufferUpdateRequest,增量为 false(根据文档为 1),X 和 Y 位置设置为 0,U16 的宽度和高度分别设置为 1366 x 768。

  2. 我收到一个带有矩形数量的 FrameBufferUpdate

  3. 我调用 drawImage 传入 Number of Rectangles 。

  4. 我从文档中假设,然后为每个矩形创建一个缓冲区到该矩形的高度和宽度。并将 BMP 上的像素设置为矩形边界。

第一个矩形总是有一个标题,并且在该标题内是请求的宽度和高度。以下矩形没有任何标题信息。所以我在这里遗漏了一些东西。我猜我还没有收到所有的第一个矩形数据,即使我已将套接字缓冲区大小设置为宽度 * 高度 * 字节。

有时我会说前 200 像素左右和全宽,尽管右侧屏幕的四分之一显示在 BMP 的左侧。有时我已经全屏了,这就是我想要的,但大多数情况下我得到一个滑行说屏幕顶部的 10 像素然后什么都没有。

我做错了什么,我知道我错了。但是什么???文档不是很好。如果有人可以通过 FrameBufferUpdateRequest -> FrameBufferUpdate -> Display Raw Pixel Data 握住我的手!!

感谢您的任何意见

克雷格

【问题讨论】:

    标签: c# protocols byte vnc


    【解决方案1】:

    我建议您参考http://tigervnc.org/cgi-bin/rfbproto,我发现它是关于协议的更好参考。特别是framebufferupdaterequestframebufferupdate 上的部分

    其他一些注意事项:

    • 您已经交换了增量值。 1 是增量请求,0 是完整请求。将增量设置为 1 时,您仅请求自上一轮以来已更改的矩形。
    • 不要假设帧缓冲区更新在您发送帧缓冲区更新后立即同步进行。您确实需要先读取第一个字节以确定服务器发送的消息类型并相应地处理消息。
    • 您确实应该根据每个矩形的实际大小创建位图(即,在您读取正在处理的矩形的大小之后。
    • 您需要考虑编码格式(您目前忽略它)。这将决定矩形的图像数据有多大。
    • 另外,我不熟悉 C# Socket.Receive 的工作原理。除非总是保证在缓冲区被填满之前一直阻塞,否则您可能需要检查实际读取了多少数据,因为服务器并不总是一次发送整个 framebufferupdate 消息,即使它们发送了,消息也可能会碎片化而不是一下子就到了。

    【讨论】:

    • 谢谢 kanaka,我确实读错了增量值!我现在只是在服务器 32bpp 上使用原始数据,只是为了在处理编码数据之前掌握所有内容。 C# Socket.Receive 是一个阻塞调用。感谢您的 cmets,我现在可以工作了
    猜你喜欢
    • 2011-11-11
    • 1970-01-01
    • 2012-06-02
    • 2011-05-30
    • 2013-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多