RFB / VNC Прием FrameBuffer и байтовых данных C # - PullRequest
0 голосов
/ 27 октября 2011

Я надеюсь, что кто-то, кто имел опыт работы с протоколом RFB, даст мне ответ.

Следуя протоколу RFB, я реализовал клиент 3.3, рукопожатие и все в порядке. Что я не понимаю или у меня есть проблемы, так это FrameUpdateRequest и FrameUpdate с использованием необработанных данных.

Я прочитал и выполнил дословную документацию @ содержание 6.4.3 и 6.5.1 из http://www.realvnc.com/docs/rfbproto.pdf

Это немного грязно, так как я играю влево, вправо и в центре. Но вот что я делаю:

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 с передачей Число прямоугольников в.

  4. Я предполагаю, что для каждого прямоугольника создайте буфер для этих прямоугольников по высоте и ширине. И установите пиксели в BMP на границы прямоугольников.

У первого прямоугольника всегда есть заголовок, а внутри этого заголовка запрошенная ширина и высота. Следующий прямоугольник не имеет никакой информации заголовка. Так что я что-то здесь упускаю. Я предполагаю, что я не получил все первые данные прямоугольников, хотя я установил размер буфера сокетов равным width * height * bytes.

Иногда я получаю, скажем, верхние 200 пикселей или около того и полную ширину, хотя четверть правого экрана отображается с левой стороны в моем BMP. Иногда у меня был полный экран, и это то, что я хочу, но в основном я получаю ползунок, скажем, 10px от верхней части экрана, затем ничего.

Я делаю что-то не так, я знаю, что это так. Но что??? Документация не велика. Если бы кто-то мог держать меня за руку через FrameBufferUpdateRequest -> FrameBufferUpdate -> Показать необработанные пиксельные данные !!

Спасибо за любой ввод

Craig

1 Ответ

0 голосов
/ 27 октября 2011

Я предлагаю вам сослаться на http://tigervnc.org/cgi-bin/rfbproto, который, как я обнаружил, является гораздо лучшей ссылкой на протокол.В частности, разделы framebufferupdaterequest и framebufferupdate

Некоторые другие примечания:

  • у вас поменялись инкрементные значения.1 является инкрементным, а 0 - полным запросом.При инкрементном значении, равном 1, вы запрашиваете только прямоугольники, которые изменились со времени последнего раунда.
  • не предполагается, что обновления кадрового буфера происходят синхронно сразу после отправки обновления кадрового буфера.Вам действительно нужно сначала прочитать первый байт, чтобы определить, какое сообщение отправлено сервером, и обработать сообщение соответствующим образом.
  • вам действительно нужно создать свое растровое изображение на основе этого фактического размера каждого прямоугольника (т.е. после того, как вы прочиталиразмер прямоугольника, который вы обрабатываете.
  • вам необходимо принять во внимание формат кодирования (в настоящее время вы его игнорируете). Это будет определять, насколько велики данные изображения для прямоугольника.
  • Кроме того, я не знаком с тем, как работает C # Socket.Receive. Если всегда не гарантируется блокировка до заполнения буфера, вам может потребоваться проверить, сколько данных было фактически прочитано, поскольку серверы не всегда отправляютвсе сообщение framebufferupdate все сразу, и даже если они это сделают, сообщения могут быть фрагментированы и не приходят все сразу.
...