2011-10-05 1819 views
1

好傢伙即時得到這個錯誤,請參閱附件>>Index and count must refer to a location within the buffer. Parameter name: bytes索引和計數必須引用緩衝區內的位置。參數名:字節

enter image description here

當使用調試器的IM我沒有得到這個錯誤,一切順利我不明白這是什麼錯誤是

這是我的服務器代碼:

IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 27015); 
      Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 
      sck.Bind(ipEnd); 
      sck.Listen(100); 

      Socket clientSocket = sck.Accept(); 

      string[] fNames = new string[3]; 
      fNames[0] = "01.jpg"; 
      fNames[1] = "02.jpg"; 
      fNames[2] = "03.jpg"; 

      string filePath = "D:\\"; 

      byte[] FilesCount = BitConverter.GetBytes(fNames.Count()); 


      clientSocket.Send(FilesCount); 

      for (int i = 0; i < fNames.Count(); i++) 
      { 
       byte[] fileNameByte = Encoding.ASCII.GetBytes(fNames[i]); 
       byte[] fileData = File.ReadAllBytes(filePath + fNames[i]); 
       byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length]; 
       byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length); 

       fileNameLen.CopyTo(clientData, 0); 
       fileNameByte.CopyTo(clientData, 4); 
       fileData.CopyTo(clientData, 4 + fileNameByte.Length); 

       clientSocket.Send(clientData); 
      } 

      clientSocket.Close(); 

和客戶端:

Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 
     clientSock.Connect(IPAddress.Parse("46.49.70.30"), 27015); 


     byte[] clientData = new byte[1024 * bt]; 
     string receivedPath = "D:/df/"; 

     byte[] FileQuantityByte = new byte[1024]; 
     clientSock.Receive(FileQuantityByte); 
     int FileQuantity = BitConverter.ToInt32(FileQuantityByte, 0); 

     for (int i = 0; i < FileQuantity; i++) 
     { 
      int receivedBytesLen = clientSock.Receive(clientData); 

      int fileNameLen = BitConverter.ToInt32(clientData, 0); 
      string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen); 

      //Console.WriteLine("Client:{0} connected & File {1} started received.", clientSock.RemoteEndPoint, fileName); 

      BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Append)); 
      bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen); 

      //Console.WriteLine("File: {0} received & saved at path: {1}", fileName, receivedPath); 

      bWrite.Close(); 
     } 

     clientSock.Close(); 

編輯:http://imageshack.us/f/202/errbk.jpg/

+0

做線之前斷言,並驗證clientData長度爲至少4 + fileNameLen。如果它與調試器正常工作,我懷疑這是一個計時問題。 clientSock.Receive()是否返回調用時在緩衝區中可用的任何字節?或者在每次接收電話之前放置1秒的延遲,看看是否有幫助。 –

回答

2

唯一的例外是在告訴究竟是什麼問題:你的一個參數是不是你認爲它應該是。

什麼是clientData的長度?當您致電Encoding.ASCII.GetString時,fileNameLen的價值是多少? bt的值是什麼,它用於初始化您的clientData陣列?

如果在調試器中沒有發生這種情況,那麼在調用之前添加一些代碼以輸出clientDatafileNameLen的值。

一個問題是clientSock.Receive可能無法一次獲得所有數據。如果您發送的文件特別大,則有可能clientSock.Receive將在沒有閱讀所有內容的情況下返回。至於Socket.Receive文件說:

如果您使用的是面向連接的插座,接收方法是可用的,直到緩衝區的大小將讀取儘可能多的數據。

可能並非所有數據都可用,或緩衝區小於文件大小。爲了確保您獲得的所有數據,你必須這樣做:

int totalBytesRead = 0; 
int bytesRead = 0; 
while ((bytesRead = clientSock.Receive(clientData, totalBytesRead, 
    clientData.Length - totalBytesRead, SocketFlags.None)) != 0) 
{ 
    totalBytesRead += bytesRead; 
} 

Receive返回0時,有沒有更多的可用數據。只有這樣你才能確定你已經收到了所有的數據。

+0

我該如何將這個應用到異步套接字,請參閱http://stackoverflow.com/questions/29102980/sending-large-message-with-socket-throws-exception?noredirect=1#comment46439159_29102980 – Smith

1

解決方案很簡單。 我有類似的問題Encoding.UTF8.GetString(array[byte], index, array[byte].Length)。 問題是,方法TAKE字節的一些計數FROM一些位置的陣中,所以你必須拿不出array[byte].Length,但小於array[byte].Length - index

如果你的數組有10個元素,並且你想從第5個位置取所有元素,則不能取10個元素。

所以,再次 - Encoding.UTF8.GetString(array[byte], FROM, TAKE)

相關問題