2015-12-09 73 views
-1

我編寫了一個客戶端=> relayserver =>客戶端桌面共享應用程序,但發送第一個映像後,客戶端發送大量的隨機數據,一些填充了隨機數據,一些填充了零。TCP客戶端無意發送

發送/接收編碼:

public static byte[] receive(TcpClient cl) 
    { 
     byte[] bsize = new byte[3]; 
     cl.GetStream().Read(bsize, 0, 3); 
     int s = (bsize[0] * 65025) + (bsize[1] * 255) + bsize[2]; 
     if (s == 0) 
     { 
      cl.GetStream().Flush(); 
      return null; 
     } 
     byte[] data = new byte[s]; 
     cl.GetStream().Read(data, 0, data.Length); 
     return data; 
    } 

    public static void send(TcpClient cl, byte[] data) 
    { 
     byte[] sdata = new byte[data.Length + 3]; 
     sdata[0] = (byte)(data.Length/65025); 
     sdata[1] = (byte)((data.Length - (sdata[0] * 65025))/255); 
     sdata[2] = (byte)(data.Length % 255); 
     for (int i = 0; i < data.Length; i++) 
     { 
      sdata[i + 3] = data[i]; 
     } 
     cl.Client.Send(sdata); 
     Console.WriteLine("Data send (" + (sdata.Length - 3) + ")"); 
    } 

在開始的時候我送的12個字節(9 + 3)的授權代碼,則沒有問題的工作原理。但是,當我發送圖像,代碼如下:

private void T_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     if (c != null) // c is a TcpClient 
     { 
      var x = s.getScreenCopy(); 

      byte[] data = ConnectionHandler.getBytes(x); 
      byte[] sdata = new byte[data.Length + 1]; 
      sdata[0] = (byte)(Command.Image); 
      for (int i = 0; i < data.Length; i++) 
      { 
       sdata[i + 1] = data[i]; 
      } 
      ConnectionHandler.send(c, sdata); 
     } 
     else 
     { 
      t.Stop(); 
     } 
    } 

客戶端不斷髮送隨機數據。該SERVERLOG看起來是這樣的:

Starting TechViewer Server... Done. 
Listening for Customer on port 30001 
Listening for Supporter on port 30000 
New connection from: 79.224.122.xxx 
Received data with length: 9 
First byte: 115 
Supportkey Received 
Generated new id: 174104133 
Send data with Length: 3 ...Done. 
Added Supporter 
New connection from: 79.224.122.xxx 
Received data with length: 9 
First byte: 99 
Clientkey Received 
Waiting for Sessionnumber from Client 
Received data with length: 3 
Id received: 174104133 
Trying to set Client 
compareing 174104133 with 174104133 
Trying to Add Client to connectedClients 
Sent id to Client 
Send data with Length: 3 ...Done. 
Client Set 
Received data with length: 188915 from 79.224.122.xxx 
Relay to Supporter 
Send data with Length: 188915 ...Done. // This is the correct Package 
Received data with length: 14231165 from 79.224.122.xxx 
Relay to Supporter 
Send data with Length: 14231165 ...Done. // Random data 
Received data with length: 16006753 from 79.224.122.xxx 
Relay to Supporter 
Send data with Length: 16006753 ...Done. // Random data 

最奇怪的是,即使我設置在它不斷髮送大量ammounts應用斷點(30之間 - 160 MB)

那麼,爲什麼會發生這種情況,以及如何我能阻止這個嗎?

增加:

Servercode用於中繼數據:

public void relayData(object state) 
    { 
     try { 
      TcpClient tclient = (TcpClient)state; 
      while (true) { 
       byte[] bytesFrom = ReadFrom(tclient); 
       if (client == tclient) { 
        RelayToSupporter(bytesFrom); 
       }else{ 
        RelayToClient(bytesFrom); 
       } 
      } 
     } catch (Exception ex) { 
      Console.WriteLine (ex.Message); 
     } 
    } 

    public void RelayToSupporter(byte[] data) 
    { 
     if (supporter.Count > 0) { 
      Console.WriteLine("Relay to Supporter"); 
     } 
     foreach (var item in supporter) { 
      try { 
       if (item.Connected) { 
        send(item, data); 
       } 
      } catch (Exception ex) { 
       Console.WriteLine (ex.Message); 
      } 
     } 
    } 

    public void RelayToClient(byte[] data) 
    { 
     if (client.Connected) { 
      Console.WriteLine("Relay to Client"); 
      send (client, data); 
     } 
    } 

編輯:

事我嘗試:

  • 只發送一個圖像,然後停止發送(結果:沒有變化)
  • 手動發送創建塊較小,則MTU(結果:沒有變化)

事情,我注意到:

  • 我想我的包計算過的地方,所以重疊的字節被解釋爲大小,這顯然是連更多錯誤。

還沒找到我的代碼中的錯誤。

+0

當您發送數據時,是否停止計時?發送整個桌面的原始圖像是大量的數據,並且考慮到你使用逐個字節的for循環來將一個緩衝區複製到另一個緩衝區,所以特別昂貴。您可能會遇到重疊的定時器調用問題,這些調用可能會疊加。請記住,數據包的大小有限,通常大約爲1500字節,因此您的發送需要多個數據包才能完成。 –

+0

@RonBeyer,你可以在serverlog中看到圖像數據大約200kb(我通過查看發送前圖像的大小來驗證它)。 for循環最多需要2ms,而timerintervall則需要200ms。我甚至試圖發送一個圖像只是一次,它給了我相同的結果 –

+0

發送200kb的數據將採取133個數據包,如果使用TCP每個人都必須做一個往返意味着接收方必須在發送方之前確認數據包可以發送另一個。即使數據包可以每毫秒1個的速率發送,您也可以在266毫秒的時間內發送數據。從你的描述來看,你的事件堆積如山,因爲線程在暫停時繼續在後臺運行。您還需要考慮傳輸時間。 –

回答

0

問題的一個很可能的來源是您在致電cl.GetStream().Read(...)時假設它將完全填充提供的緩衝區,但不一定是這種情況。因此,您的初始圖像緩衝區可能不會被完全填充,因此您的下一個字節解釋爲大小標題實際上是來自第一個圖像中間的字節,給您意想不到的大小。

任何時候您從網絡流中獲取Read(...),您需要檢查返回值以確定返回了多少數據(,如果有)。

,如果你想從流讀取的字節的具體數量我會建議使用這樣的幫手:

private byte[] ReadData(TcpClient client, int numBytes) 
{ 
    var data = new byte[numBytes]; 
    var totalBytes = 0; 
    while (totalBytes < data.Length) 
    { 
     var bytesRead = client.GetStream().Read(data, totalBytes, data.Length - totalBytes); 
     if (bytesRead == 0) break; 
     totalBytes += bytesRead; 
    } 
    if (totalBytes != data.Length) 
    { 
     // This will occur when the other end of the connection is closed (and so Read() returns zero). 
     // You can throw an exception, return null etc. depending on your requirements 
     ... 
    } 
    return data; 
} 

,每當你想從流中讀取的字節一個確切的數字,應該使用該,即使只是你的3字節大小的頭文件,因爲這可能會通過例如3個獨立的1字節Read() s。

我也注意到你的頭字節值的計算是相當奇怪的。您可能需要考慮擴展爲4字節的標頭(如果字節爲int,則將其大小),然後利用框架的BitConverter.GetBytes(int)BitConverter.ToInt32(...)將大小轉換爲字節數組並再次返回。