2

インデックスをスローし、カウントはバッファ内の場所を参照する必要があります。3つ以上のクライアントがサーバーに接続されており、バイトデータがグローバル変数として宣言されている場合のパラメーター名bytes例外。

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)
}
4

1 に答える 1

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

もちろん、これを修正しても、コメントでほのめかした別の問題があります。バッファに返されるデータの量は保証されません。からの戻り値を調べる必要がありますEndReceiveReceive実際にメッセージを作成するまで、への複数の呼び出し(または道徳的な同等物)を組み合わせる必要がある場合があります。Send一方の端への呼び出しともう一方の端の呼び出しの間には、1対1の対応はありませんReceive

最後に、を使用していることを示しましたが、クラスTcpClientの操作を使用していますか?あなたがあなたに与えるをSocket使用していない理由は何ですか?(ここではあまり違いがないわけではありません)。NetworkStreamTcpClient

于 2012-09-14T14:39:59.303 に答える