2013-08-27 540 views
3

我已經實現了多個客戶端和服務器。客戶端以2分鐘的固定間隔向服務器發送大小爲238或564的tcp數據包。數據包的結構如下c#源數組不夠長。檢查srcIndex和長度,以及陣列的下限Array.Copy

1)數據包標頭 - 44字節 該標頭大小不會改變,並隨每個數據包附帶。

2)報頭超過1個數據包後,這些數據包的大小爲16或32個字節。這些數據包的數量隨着每個來自客戶端的數據包而變化,這些數據包的數量決定了數據包的總大小(238或512)。

3)最後2個字節是crc,它也是固定不變的。

我的服務器從客戶端接收數據包,並從主數據包中分離數據包,解析它們並將其寫入excel文件。以下是我的代碼

服務器代碼

private void createserver(int no_of_clients) 
    { 
     tcpListener = new TcpListener(ipAddress, Globals.port_number); 
     tcpListener.Start(); 

     for (int i = 0; i < no_of_clients; i++) 
     { 
      Thread newThread = new Thread(new ThreadStart(Listeners)); 
      newThread.Start(); 
     } 
    } //End of createserver(); 

public void Listeners() 
    { 
     Socket socketForClient; 

      socketForClient = tcpListener.AcceptSocket(); 



     if (socketForClient.Connected) 
     { 
      NetworkStream networkStream = new NetworkStream(socketForClient); 

      int stream_size = 0; 
      while (true) 
      { 
       byte[] raw_stream = new byte[1024]; 

       do 
       { 
        try 
        { 
         stream_size = networkStream.Read(raw_stream, 0, 1024); 
        } 
        catch (IOException e) 
        { 
         if (e.InnerException is SocketException) 
         { 
          MessageBox.Show("The client has disconnected"); 
          foreach (Socket s in active_clients) 
          { 
           if (s == socketForClient) 
           { 
            MessageBox.Show(string.Format("Client {0} has forcibly exited", s.RemoteEndPoint)); 
            infoBox1.Text = infoBox1.Text + "\r\n" + string.Format("Client {0} has forcibly exited", s.RemoteEndPoint); 
           } 
          } 
         } 
         return; 
        } 
       } 
       while (networkStream.DataAvailable); 

       byte[] input_data = new byte[stream_size]; 
       byte[] input_data1 = new byte[stream_size]; 
       Array.Copy(raw_stream, 0, input_data, 0, stream_size); 

       if (Encoding.ASCII.GetString(input_data) != Globals.exit_code) 
       { 
        Datapackparser(input_data, input_data.Length, 0, socketForClient); 
       } 
     } 
     } 

public static void Datapackparser(byte[] packet, int input_length, int indexno, Socket sk)) 
    { 
     //remove header and crc from end of packet since I know every time it will be same      

      // for separating data packets and parsing them on basis of packet id which comes with every individual data packets 

      data_pkts_index = 44; // since data packets start at 44. 0-43 is header 
      int size_1_data_pkts = 0; 
      string pkt_ids = ""; 

      while (data_pkts_index < tcp_pkt_size - 2) 
      { 
       // first 2 bytes of each data packet is size of that data packet 16 or 32 
       size_1_data_pkts = Convert.ToInt32(string.Format(BitConverter.ToString(packet, data_pkts_index + 1, 1) + 
        BitConverter.ToString(packet, data_pkts_index, 1)), 16); 
       // next 1 byte is packet id of each data packet on basis of which I parse them 
       pkt_ids = Convert.ToInt32(packet[data_pkts_index + 2]).ToString("X"); 
       // this function is for parsing each data packet 
       data_pkt_func(data_pkts_index, size_1_data_pkts, pkt_ids, packet, imei); 
       data_pkts_index = data_pkts_index + size_1_data_pkts;time it will be same. 

      } 
     } 

static private void data_pkt_func(int ind, int size, string code_packet, byte[] pkt, string file1) 
    { 
     byte[] pass_packet = new byte[size]; 
     Array.Copy(pkt, ind, pass_packet, 0, size); 

     if (code = "a") 
     { // one type of packet 
     } 
     else if (code = "dsd") 
     { // 2nd type of packet 
     } 
     else if ...... 
     { 
     } 
     // like this their are 8-9 types of data packet 
    } 

問題,我面對的是,這個代碼能夠正確地分析數據包在一定程度上。例如,第一數據包10-11服務器接收後該異常被正確但隨後解析「源陣列不夠長,檢查SRCINDEX和長度,並且該陣列的下限」在線

Array.Copy(pkt, ind, pass_packet, 0, size); 
拋出

的 '尺寸' 值突然跳到4096

堆棧跟蹤被以下

在System.Array.Copy(陣列sourceArray,的Int32 sourceIndex,陣列destinationArray, INT32 destinationIndex,INT32長度,布爾可靠)

在System.Array.Copy(陣列sourceArray,INT32 sourceIndex,陣列destinationArray,INT32 destinationIndex,INT32長度)

在Packet_parsing.client_pkt_parsing.data_pkt_func(INT32 IND,INT32在WindowsFormsApplication1 \ packet_parser.cs中:line 357

at Datapackparser(Byte [] packet,Int32 input_length,Int32 indexno,Socket sk)在WindowsFormsApplication1 \ packet_parser.cs中的大小,字符串code_packet,Byte [] pkt,String file1) line 847

at WindowsFormsApplication1 .Form1.Listeners()在\ WindowsFormsApplication1 \ Form1.cs中:線385

在System.Threading.ThreadHelper.ThreadStart_Context(對象狀態)

在System.Threading.ExecutionContext.Run(的ExecutionContext的ExecutionContext,ContextCallback回調,對象的狀態,布爾ignoreSyncCtx)

在System.Threading.ExecutionContext.Run(的ExecutionContext的ExecutionContext,ContextCallback回調,對象狀態)

在System.Threading.ThreadHelper。ThreadStart()

所以,任何人都可以幫我解決這個錯誤?

+2

可能不是直接相關的,但是你的循環代碼被嚴重破壞 - 你可能會對'networkStream.Read'發出多次調用,並且只保留'stream_size'中返回的最後一個值。而且你總是從緩衝區開始覆蓋。你應該積累'stream_size'並將它作爲第二個參數(而不是'0')傳遞給'Read'(並且相應地調整長度) –

回答

1

您是否在十六進制編輯器中查看數據包以查看數據包大小是否在數據包中正確寫入?我將首先捕獲異常並將數據包轉儲到文件以供進一步檢查。

另外,你確定你的號碼解析代碼是正確的嗎?第一個「Convert.ToInt32」行很複雜,我找不到任何將「Convert.ToInt32」列爲兩個參數的文檔。我懷疑如果你修復了這條線,你會解決這個問題。

+1

['Convert.ToInt32(String,Int32)'](http:// msdn .microsoft.com/EN-US /庫/ 1k20k614.aspx)? –

+0

哈哈,謝謝。不知道爲什麼我找不到。 – piojo

+0

數據包大小是正確的,因爲我能夠正確解析前幾個數據包,並在正確解析了10-11個數據包後發出異常。 – prattom

0

好吧,我發現問題出在客戶端。由於客戶端存在一些錯誤,客戶端在正確發送10-12個數據包之後向數據包添加了額外的0。我沒有訪問客戶端,我編寫我的服務器的基礎上給我的規範,因此我不知道有關的錯誤和客戶端開發人員也不知道這個錯誤。感謝所有的答案。