/// <summary>
        /// 发送消息
        /// </summary>
        private void GetSendMessage()
        {
            IPEndPoint epF = new IPEndPoint(IPAddress.Parse(this.friendChatIP.Split(':')[0]), Convert.ToInt32(this.friendChatIP.Split(':')[1]));
            try
            {
                //将richTextBoxSend富文本中的Rtf格式文字转换为字节数组
                byte[] _byte = Encoding.ASCII.GetBytes(richTextBoxSend.Rtf);
                //以1024为单位判断有多少个数据包
                int packetSendMessage = (int)(_byte.Length / (long)1024);
                //获取剩下不够1024的字节长度
                int lastPacketSendMessage = (int)(_byte.Length - (packetSendMessage * (long)1024));
                byte[] buffer = Encoding.Unicode.GetBytes(string.Format("{0}{1}|{2}", Config.CHATHEAD, Config.loginId, this.userName));                
                //向服务器发送消息头
                socketChat.SendTo(buffer, epF);
                int sendLength = 0;
                int intlength = 1024;
                //开始遍历数据包并发送
                for (int i = 0; i < packetSendMessage; i++)
                {
                    //判断当前数据包是足够1KB
                    if (_byte.Length >= i * 1024 + 1024)
                    {
                        //从 _byte变量中截取1024位
                        string content = Encoding.ASCII.GetString(_byte, i * 1024, i * 1024 + 1024);
                        buffer = Encoding.ASCII.GetBytes(content);
                        //将数据包头转换成字节数组
                        byte[] temp = Encoding.Unicode.GetBytes(Config.CHATMSG);
                        //向服务器发送聊天消息,ToBuffer为将_byte和temp两个数据合并成一个,返回byte[]类型
                        socketChat.SendTo(ToBuffer(buffer, temp, buffer.Length, temp.Length), epF);
                        Thread.Sleep(20);
                    }
                }
                //判断是否还有剩下的数据包,有就一并发送
                if (lastPacketSendMessage != 0)
                {
                    string content = Encoding.ASCII.GetString(_byte, sendLength, lastPacketSendMessage);
                    buffer = Encoding.ASCII.GetBytes(content);
                    byte[] temp = Encoding.Unicode.GetBytes(Config.CHATLASTMSG);
                    //向服务器发送聊天消息
                    socketChat.SendTo(ToBuffer(buffer, temp, buffer.Length, temp.Length), epF);
                }
                //清空输入框
                richTextBoxSend.Text = string.Empty;
            }
            catch (Exception exp)
            {
                byte[] buffer =new byte[0];
                byte[] temp = Encoding.Unicode.GetBytes(Config.CHATLASTMSG);
                //向服务器发送聊天消息
                socketChat.SendTo(ToBuffer(buffer, temp, buffer.Length, temp.Length), epF);
                ShowMessage(string.Format("向好友发送消息出错:" + exp.Message), MessageBoxIcon.Error);
            }
        }
如果发消息过多,会提示这个
"索引和计数必须引用该缓冲区内的位置,参数名:bytes"
这是什么意思呀?我调试过了,确实是没有数组越界呀。发送的文字多的话,会截取成多个片段发送,第一个片段发送成功了,第二个或后面的就不行了。就提示这个。

解决方案 »

  1.   

    改进方案:1. 分包数量的判断貌似写错了?
     int packetSendMessage = (int)(_byte.Length / (long)1024);
     //应该改成 
     int packetSendMessage = (int)(_byte.Length / (long)1024) + 1;
     2. 为啥发送的时候要用SendTo? 直接Send不可以吗?建议改进。
      

  2.   

    1、没有写错,后面有判断不足一个包的字节部分的。
    2、因为是用的UDP发送的,而不是TCP,要是TCP就不需要人工分包了。
      

  3.   

    错误在这里:
    string content = Encoding.ASCII.GetString(_byte, i * 1024, i * 1024 + 1024);
    第三个参数应该是1024,而不是i * 1024 + 1024,它代表要发送的字节数,而不是结束位置。另外你没必要这么麻烦,这样写就可以了。
                    for (int i = 0; i < packetSendMessage; i++)
                    {
                        //判断当前数据包是足够1KB
                        if (_byte.Length >= i * 1024 + 1024)
                        {
                            //向服务器发送聊天消息
                            socketChat.SendTo(_byte, i * 1024, 1024, SocketFlags.None, epF);
                            Thread.Sleep(20);
                        }
                    }
      

  4.   

    你上面的这个问题我今天正好处理过.我是用tcp发送的数据,同时处理分包和接受后合包.tcp分包主要是因为tcp会粘包.原理很简单就是将长度放在包头一起发送.你上面用的是udp在其实在分包与合包上区别不大.只不过UDP无序需要携带顺序.但UDP不会粘包.