RFB/VNC接收帧缓冲区和字节数据问题c#
本文关键字:字节数 字节 数据 问题 缓冲区 VNC RFB | 更新日期: 2023-09-27 18:12:36
我希望有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);
}
我为这段代码感到抱歉,我经历了这么多的排列,把它弄得一团糟。
这就是我正在尝试做的事情,我想象它应该按照协议工作的方式:
我请求一个framebufferedaterequest,增量是假的(1,根据Doc的),X和Y位置设置为0和宽度&
我收到一个带有矩形数量的FrameBufferUpdate
我调用drawImage传递矩形数
我从文档中假设,然后为每个矩形创建一个缓冲区,该矩形的高度和宽度。并将BMP上的像素设置为矩形边界。
第一个矩形总是有一个头,并在该头中请求的宽度和高度。下面的矩形没有任何标题信息。所以我遗漏了一些东西。我猜我没有收到所有的第一个矩形数据,即使我已经设置套接字缓冲区大小为宽度*高度*字节。
有时我看到顶部200像素左右,全宽,尽管右手屏幕的四分之一显示在我的BMP的左手边。有时我需要全屏,这是我想要的,但大多数情况下,我得到一个滑块,比如屏幕顶部的10px,然后什么也没有。
我知道我做错了什么事。但是什么? ?文档不是很好。如果有人能牵着我的手通过framebufferedaterequest -> FrameBufferUpdate ->显示原始像素数据!!谢谢你的输入
克雷格我建议您参考http://tigervnc.org/cgi-bin/rfbproto,我发现这是一个更好的协议参考。特别是关于framebufferedaterrequest和framebufferupdate
的部分其他注释:
- 您的增量值被交换。1是增量请求,0是完整请求。增量设置为1时,您只请求自上一轮以来已更改的矩形。
- 不要假设在发送framebufferupdate之后立即同步进行framebuffer更新。您确实需要首先读取第一个字节,以确定服务器发送了哪种类型的消息,并相应地处理消息。
- 你应该根据每个矩形的实际大小来创建你的位图(即在你读取你正在处理的矩形的大小之后)。
- 你需要考虑编码格式(你目前忽略了它)。这将决定矩形图像数据的大小。
- 另外,我不熟悉c# Socket。接收工作。除非它总是保证阻塞直到缓冲区被填满,否则您可能需要检查实际读取了多少数据,因为服务器并不总是一次发送整个framebufferupdate消息,即使它们这样做,消息也可能被分割,而不是一次到达。