簡體   English   中英

C#從套接字讀取錯誤的數據

[英]C# reading wrong data from socket

我正在嘗試通過一個套接字向另一個套接字發送隨機單詞。 我為數據管理設計了一個簡單的協議,每個數據包的前4個字節中包含實際消息的長度(以字節為單位),然后是消息本身。

這是客戶端代碼:

    private byte[] sendBuffer = new byte[1000];
    private Socket sSocket;
    private void WriteDataLength(int length)
    {
        sendBuffer[0] = (byte)(length);
        sendBuffer[1] = (byte)(length >> 8);
        sendBuffer[2] = (byte)(length >> 16);
        sendBuffer[3] = (byte)(length >> 24);
    }
    private void DoWork()
    {
        while (true)
        {
            string word = RandomString(random.Next(1, 10)); //generates a random string.
            byte[] toBytes = Encoding.ASCII.GetBytes(word); //converting the string to byte array.
            int length = toBytes.Length; // length of the actual data(the word length).
            WriteDataLength(length);//writing the word length in bytes.
            Buffer.BlockCopy(toBytes, 0, sendBuffer, 4, toBytes.Length);//copying the array which hold the word to the sendBuffer (start from the 4th byte).
            sSocket.Send(sendBuffer, length+4 , SocketFlags.None);//send +4 bytes for the length prefix.        
        }
    }
    private static Random random = new Random();         
    public static string RandomString(int length)
    {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        return new string(Enumerable.Repeat(chars, length)
          .Select(s => s[random.Next(s.Length)]).ToArray());
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        TcpClient tcpClient = new TcpClient();
        tcpClient.Connect("localhost", 10);
        sSocket = tcpClient.Client;
        Thread th = new Thread(DoWork);
        th.Start();
    }

如您所見,我生成一個隨機字,將其寫入前4個字節(只需將位移位),然后將其復制到sendBuffer。

服務器代碼:

    private byte[] recieveBuffer = new byte[1000];
    TcpListener tListener;
    Socket rSocket;
    private int readData()
    {
        rSocket.Receive(recieveBuffer, 0, 4, SocketFlags.None); //read the first 4 bytes
        int size = getDatalength(); //reassemble the bytes to the original value.
        int dataleft = size;
        int totalread = 4; //read already 4 bytes.
        int recv;
        while (totalread < size)
        {
            recv = rSocket.Receive(recieveBuffer, totalread, dataleft, 0);
            if (recv == 0) //stop reading
            {
                break;
            }
            totalread += recv;
            dataleft -= recv;
        }
        return size;
    }


    private int getDatalength()
    {
        int length = recieveBuffer[0] | recieveBuffer[1] << 8 | recieveBuffer[2] << 16 | recieveBuffer[3] << 24;
        return length;
    }
    private void DoWork()
    {
        while (true)
        {
            int length = readData();
            byte[] word = new byte[length]; //initializing a new array to hold the word
            Buffer.BlockCopy(recieveBuffer, 4, word, 0, length); //copying to the recieveBuffer from the 4th place( first 4 bytes are always length header).
            string result = Encoding.ASCII.GetString(word);
            Console.WriteLine(result);
        }
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        tListener = new TcpListener(IPAddress.Any, 10);
        tListener.Start();
        rSocket = tListener.AcceptTcpClient().Client;
        Thread th = new Thread(DoWork);
        th.Start();

    }

在服務器端,我讀取前4個字節以獲取長度(這樣我就知道必須讀取多少字節),然后我開始循環直到數據大小結束。

我實際上不知道如何解釋它, 它可以工作2或3秒鍾 ,然后Server在此行中拋出System.ArgumentOutOfRangeException期望:

recv = rSocket.Receive(recieveBuffer,totalread,dataleft,0);

我調試了它,發現size變量包含非常大的數字...(例如幾百萬),所以我想問題出在讀取前4個字節...

我還嘗試輸出recieveBuffer的前4個值,它們與客戶端中的值不同。(拋出異常時,它們是相同的)。

我不確定這是怎么回事..我將感謝您的幫助。

謝謝。

…您的計算中存在錯誤:比較totalread <size時,size不包括消息長度的4個字節,但是您已經將它們添加到totalread中,因此您應該從0開始忽略totalread而不考慮4個字節長度,否則您的編寫代碼應將它們加到總長度中。 – o_weisman

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM