【问题标题】:How to Convert int to byte array and byte array to Int again? (Edit)如何将 int 转换为字节数组和字节数组再次转换为 Int? (编辑)
【发布时间】:2022-06-20 18:57:10
【问题描述】:

我正在使用 UDP 协议发送 68 字节的数据。

68bytes 数据由 4byte int 和随机 64byte byte 数组组成。 uint seqzero 开头,如果客户端一次向服务器发送一次数据报,它将增加。我使用BitConverter.GetBytes作为数据的seq来制作字节数组。

public class NewData
{
    public uint seq;
    public byte[] data = new byte[64];

    public NewData()
    {
        seq = 0;
        data = null;
    }

    public NewData(uint seq, byte[] data)
    {
        this.seq = seq;
        this.data = data;
    }
}

服务器有 2 个线程。 1 个线程将Enqueue,另一个线程将Dequeue。 (生产者和消费者线程)

我试图检查数据是否顺利。

private readonly ConcurrentQueue<NewData> queue = new ConcurrentQueue<NewData>();


private void ReceiveThread()
{
    int recv;
    uint seq = 0;
    byte[] datagram = new byte[1024];
    List<byte> list = new List<byte>(); // for enqueue seq test

    while (true)
    {
        autoresetevent.WaitOne();

        if (Dispatcher.Invoke(() => (string)StartButton.Content == "Stop"))
        {
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 

            socket.Bind(endpoint);
            socket.Blocking = false;

            IPEndPoint sender = new IPEndPoint(IPAddress.Any, Dispatcher.Invoke(() => Convert.ToInt32(portTextBox.Text)));
            EndPoint tmpRemote = (EndPoint)sender;

            while (true)
            {
                try
                {
                    recv = socket.ReceiveFrom(datagram, ref tmpRemote);
                }
                catch (SocketException e)
                {
                    Thread.Sleep(threadSleep);  
                    continue;
                }

                ////------------------------------------------------------------------------
                //// To Test Datagram Sequence
                ////------------------------------------------------------------------------
                //for (int i = 0; i < 4; i++)
                //{
                //    list.Add(datagram[i]);
                //}
                //Debug.Write(Convert.ToString(BitConverter.ToUInt32(list.ToArray(), 0)) + " ");
                //list.Clear();

                NewData newdata = new NewData(seq, datagram);
                queue.Enqueue(newdata);

                ////------------------------------------------------------------------------
                //// To check queue Count. if, queue Count = Client packet sent, no packet lost 
                ////------------------------------------------------------------------------
                //Debug.Write(Convert.ToString(queue.Count()) + " ");

                seq++; 

                if (Dispatcher.Invoke(() => (string)StartButton.Content == "Start"))
                {
                    socket.Close();
                    break;
                }
                Thread.Sleep(threadSleep);
            }
        }
    }
}
private void FileSaveThread()
{
    uint packet_lost = 0;
    uint oldValue = 0;
    uint currentValue = 0;
    int j = 0; // for index

    List<byte> sequenceList = new List<byte>(); // sequenceList

    while (true)
    {
        autoresetevent2.WaitOne()
        NewData newdata = new NewData(); 

        if (queue.TryDequeue(out newdata))
        {
            for (j = 0; j < 4; j++)
                sequenceList.Add(newdata.data[j]);
            oldValue = BitConverter.ToUInt32(sequenceList.ToArray(), 0); // oldValue에 현재값 저장

            queue.TryPeek(out newdata);
            for (j = 0; j < 4; j++)
                sequenceList.Add(newdata.data[j]);
            currentValue = BitConverter.ToUInt32(sequenceList.ToArray(), 0); // oldValue에 현재값 저장
                                                                             //Debug.Write(Convert.ToString(currentValue) + " ");
            sequenceList.Clear();

            if (!(currentValue == oldValue + 1))
            {
                packet_lost++;
                Dispatcher.Invoke(() => dataResultTextBox.Text += " Packet_Lost : " + packet_lost + "\n");
            }
        }
        Thread.Sleep(threadSleep);
    }
}

973 后数据报的 seq 缺失。

Debug.Write() 说 ... 970 971 972 974 977 981 984 987 991 994 998 1001 1004 1007 1010 1014 1017 1021 1023 1027 1030 1034 1037 ...

由于数据报序列一次增加1,为什么间隔会改变?

或者我应该考虑将字节数组更改为 Int 的其他方法吗?

编辑)我每 10 毫秒发送一次数据。它在我每 100 毫秒发送一次数据时起作用。

客户端代码

private async void DataSender(int num, int cycle, string ip, int port)
{

    uint dataSequence = 0; 

    byte[] data = new byte[64]; // 64byte data 
    byte[] byteDataSeq = new byte[4]; // int sequence to byte
    byte[] datagram = new byte[1024]; // seq + data
    List<byte> datagramList = new List<byte>(); 

    IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ip), port); // 서버의 주소 지정
    Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); // udp 소켓 client 선언

    while (true)
    {
        if ((string)startButton.Content == "Start")
        {
            break;
        } 

        random.NextBytes(data); 

        byteDataSeq = BitConverter.GetBytes(dataSequence); 
        datagramList.AddRange(byteDataSeq); 
        datagramList.AddRange(data);

        datagram = datagramList.ToArray(); 
        datagramList.Clear(); 

        client.SendTo(datagram, ep); 
        dataSequence++;

        await Task.Delay(cycle);
    }
}

【问题讨论】:

  • 可能是丢包,因为这是udp。
  • 可能是丢包...我每 10 毫秒发送一次数据。它在我每 100 毫秒发送一次数据时起作用。
  • 数据包丢失也可能是接收缓冲区溢出造成的。数据怎么发送,数据有多大,休眠时间多长? 10ms 的间隔有效,但 100ms 似乎并非不合理。
  • 如何控制接收缓冲区溢出?
  • 试试更大的ReceiveBufferSize,看看丢失的数字是否变大了。

标签: c# bitconverter


【解决方案1】:

不要在出队线程中设置任何睡眠,因为客户端发送数据的速度非常快。 出队线程的睡眠时间不应超过客户端。或者不要让他们睡觉。

【讨论】:

    猜你喜欢
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 2023-03-03
    • 2022-12-06
    相关资源
    最近更新 更多