2012-09-14 73 views
2

它引發索引並且計數必須引用緩衝區中的位置。當超過3個客戶端連接到服務器時,參數名稱字節異常&字節數據被聲明爲全局變量。索引和計數必須引用緩衝區內的位置。參數名稱字節

private void OnReceive(IAsyncResult ar)   
{   
    try 
    { 
     clientSocket.EndReceive(ar); 

     Data msgReceived = new Data(byteData); 
     //Accordingly process the message received 
     switch (msgReceived.cmdCommand) 
     { 
      case Command.Login: 
       //lstChatters.Items.Add(msgReceived.strName); 
       break; 

      case Command.Logout: 
       lstChatters.Items.Remove(msgReceived.strName); 
       break; 

      case Command.Message: 
       break; 

      case Command.List: 
       lstChatters.Items.AddRange(msgReceived.strMessage.Split('*')); 
       lstChatters.Items.RemoveAt(lstChatters.Items.Count - 1); 
       txtChatBox.Text += "<<<" + strName + " has joined the room>>>\r\n"; 
       break; 
     } 

     if (msgReceived.strMessage != null && msgReceived.cmdCommand != Command.List) 
      txtChatBox.Text += msgReceived.strMessage + "\r\n"; 

     byteData = new byte[1024]; 

     clientSocket.BeginReceive(byteData, 
            0, 
            byteData.Length, 
            SocketFlags.None, 
            new AsyncCallback(OnReceive), 
            null); 

    } 
    catch (ObjectDisposedException) 
    { } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message, "ClientTCP: " + strName, MessageBoxButtons.OK, MessageBoxIcon.Error); 
    } 
} 

這是用於管理服務器和客戶端之間的數據通信類數據:

class Data 
{ 
    //Default constructor 
    public Data() 
    { 
     this.cmdCommand = Command.Null; 
     this.strMessage = null; 
     this.strName = null; 
    } 

    //Converts the bytes into an object of type Data 
    public Data(byte[] data) 
    { 
     //The first four bytes are for the Command 
     this.cmdCommand = (Command)BitConverter.ToInt32(data, 0); 

     //The next four store the length of the name 
     int nameLen = BitConverter.ToInt32(data, 4); 

     //The next four store the length of the message 
     int msgLen = BitConverter.ToInt32(data, 8); 

     //This check makes sure that strName has been passed in the array of bytes 
     if (nameLen > 0) 
      this.strName = Encoding.UTF8.GetString(data, 12, nameLen); 
     else 
      this.strName = null; 

     //This checks for a null message field 
     if (msgLen > 0) 
      this.strMessage = Encoding.UTF8.GetString(data, 12 + nameLen, msgLen); 
     else 
      this.strMessage = null; 
    } 

    //Converts the Data structure into an array of bytes 
    public byte[] ToByte() 
    { 
     List<byte> result = new List<byte>(); 

     //First four are for the Command 
     result.AddRange(BitConverter.GetBytes((int)cmdCommand)); 

     //Add the length of the name 
     if (strName != null) 
      result.AddRange(BitConverter.GetBytes(strName.Length)); 
     else 
      result.AddRange(BitConverter.GetBytes(0)); 

     //Length of the message 
     if (strMessage != null) 
      result.AddRange(BitConverter.GetBytes(strMessage.Length)); 
     else 
      result.AddRange(BitConverter.GetBytes(0)); 

     //Add the name 
     if (strName != null) 
      result.AddRange(Encoding.UTF8.GetBytes(strName)); 

     //And, lastly we add the message text to our array of bytes 
     if (strMessage != null) 
      result.AddRange(Encoding.UTF8.GetBytes(strMessage)); 

     return result.ToArray(); 
    } 

    public string strName;  //Name by which the client logs into the room 
    public string strMessage; //Message text 
    public Command cmdCommand; //Command type (login, logout, send message, etcetera) 
} 
+0

使用堆棧跟蹤更好地發佈確切的異常。而且,這個byteData看起來不是全局的。 –

+0

您可能發送的消息大於'byteData'(1024)的大小嗎? –

+0

你正在做的一個糟糕的假設是,你調用BeginReceive(byteData,0,byteData.Length ...)將會用' byteData.Length'字節數據。請注意您的代碼當前忽略的['EndReceive'](http://msdn.microsoft.com/en-us/library/w7wtt64b)的返回值。 –

回答

0

要解決的第一問題,沒有byteData是一個全球性的。使它成爲一個地方,而不是:

private void OnReceive(IAsyncResult ar)   
{   
    byte[] byteData; 

然後,它傳遞的state參數BeginReceive

byteData = new byte[1024]; //Line 1 

clientSocket.BeginReceive(byteData, 
             0, 
             byteData.Length, 
             SocketFlags.None, 
             new AsyncCallback(OnReceive), 
             byteData); 

而且從IAsyncResult使用它之前,當你完成接收的恢復它:

clientSocket.EndReceive(ar); 
byteData = (byte[])ar.AsyncState; 

Data msgReceived = new Data(byteData); //Line2 

當然,固定這個,你還是在我的評論中提到了另一個問題 - 無法保證有多少數據會返回到緩衝區 - 您需要檢查EndReceive的返回值。您可能必須將多個呼叫合併到Receive(或其道德等值),直到您實際建立一條消息。在一端的Send的呼叫與另一端的Receive的呼叫之間沒有一對一的對應關係。

最後,您已經表明您正在使用TcpClient,但您正在使用Socket類的操作?你爲什麼不使用TcpClient給你的NetworkStream? (這並不是說這裏有太大的區別)。

+0

我正在使用套接字,我遇到同樣的問題,請參閱http://stackoverflow.com/questions/7665162/index-and-count-must-refer-to-a-location-within-the-buffer-parameter-name-byte我如何應用這個解決方案 – Smith

相關問題