c#源数组不够长.检查srcIndex和长度,以及数组';s的Array.Copy的下限

本文关键字:数组 Copy Array 检查 不够 srcIndex | 更新日期: 2023-09-27 18:29:04

我已经实现了多个客户端和服务器。客户端以2分钟的固定间隔向服务器发送大小为238或564的tcp数据包。数据包的结构遵循

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(Array sourceArray,Int32 sourceIndex,Array destinationArray,Int32-destinationIndex,Int32-length,布尔可靠)

在System.Array.Copy(Array sourceArray,Int32 sourceIndex,Array destinationArray,Int32-destinationIndex,Int32-length)

在WindowsFormsApplication1''Packet_parser.cs:line 357 中的Packet_parsing.client_pkt_parsing.data_pkt_func(Int32 ind,Int32 size,String code_Packet,Byte[]pkt,String file1)

在WindowsFormsApplication1''packet_parser.cs:line 847 中的数据包解析器(Byte[]packet,Int32 input_length,Int32 indexno,Socket sk)

位于''WindowsFormsApplication1''Form1.cs:line 385 中的WindowsFormsApplication1.Form1.Listeners()

位于System.Threading.ThreadHelper.ThreadStart_Context(对象状态)

在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态,布尔ignoreSyncCtx)

在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态)

位于System.Threading.ThreadHelper.ThreadStart()

所以有人能帮我解决这个错误吗?

c#源数组不够长.检查srcIndex和长度,以及数组';s的Array.Copy的下限

好的,我发现问题出在客户端。由于客户端出现一些错误,客户端在正确发送10-12个数据包后,向数据包添加了额外的0。我无法访问客户端,我已经根据给我的规范对服务器进行了编码,因此我不知道这个bug,客户端开发人员也不知道这个bug。感谢所有的回答。

您是否在十六进制编辑器中查看了数据包,以查看数据包中是否正确写入了数据包大小?我会先捕获异常,然后将数据包转储到一个文件中进行进一步检查。

另外,你确定你的号码解析代码是正确的吗?第一行"Convert.ToInt32"很复杂,我找不到任何文档将"Convert.To Int32"列为使用两个参数。我怀疑如果你解决了这条线,你就会解决问题。