简体   繁体   中英

C# Socket.Receive() malfunctions when TCP package is larger than MTU

I'm using C# Socket class to send/receive TCP messages to/from our server by short connection. The pseudo-code (exclude some false tolerant logic to make it clear) is as followings.

class MyTCPClient {
    private Socket mSocket;

    MyTCPClient() {
        mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    }

    void Connect(ipEndpoint, sendTimeOut, receiveTimeOut) {
        mSocket.Connect(ipEndpoint);
        mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, sendTimeOut);
        mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, receiveTimeOut);
    }

    void Send(msg) {
        mSocket.Send(msg);
    }

    void Receive(data) {
        ByteStreamWriter bsw = new ByteStreamWriter();
        int totalLen = 0;
        while (true) {
            byte[] temp = new byte[1024];
            int len = mSocket.Receive(temp, SocketFlags.None);
            System.Threading.Thread.Sleep(50);  // This is the weirdest part
            if (len <= 0) break;
            totalLen += len;
            bsw.WriteBytes(temp);
        }
        byte[] buff = bsw.GetBuffer();
        data = new byte[totalLen];
        Array.Copy(buff, 0, data, 0, totalLen);
    }

    ~MyTCPClient() {
        mSocket.Close();
    }
}

I was using this class to request the same message from our server several times by short connection, and the following things occurred (only when the message size was larger than one MTU -- 1500 bytes).

  1. If the "Sleep(50)" was commented out, the most of the times (90%) I received wrong "data", specifically to say, the "totalLen" was right, but the "data" was wrong.
  2. If I replaced "Sleep(50)" to "Sleep(10)", about half of the times I received wrong "data", and "totalLen" was also right always.
  3. If I used "Sleep(50)", occasionally, I received wrong "data".

I can guarantee that, every time, our server sent the right data, and the client received the right data too at TCP layer (I used WireShark to monitor all messages through the port I used). Is there anyone who can help to answer why my C# code cannot get the right data?

Also, if I use mSocket.Available instead of the return value of Socket.Receive() to judge the while loop, I would always get the right data and data length...

You don't truncate temp to len bytes before writing it. All the bytes after len in temp have not been filled with current data and thus contain nonsensical, stale date.

When copying to another stream you could use stream.Write(temp, 0, len)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM