Linux/Mono抛出ArgumentOutOfRangeException,而Windows则没有

nat*_*tli 0 c# mono

尝试将数据从TcpClient缓冲区读取到字节数组中:

private byte[] excessData;
public bool receiveMessage(ref string recvStr, string daddy = "")
{
    recvStr = "";
    CSocket_PacketProtocol packprot = new CSocket_PacketProtocol(0, this);

    WriteDebugWithTimestamp("receiveMessage obtaining client NetworkStream - daddy = " + daddy);
    NetworkStream nStream = client.GetStream();
    WriteDebugWithTimestamp("receiveMessage client NetworkStream obtained, entering receive loop");

    int bytesRead = 0;
    do
    {
        if (!packprot.done)
        {
            try
            {
                byte[] inStream = new byte[10025]; //We'll read into this stream

                int buffSize = client.ReceiveBufferSize;
                WriteDebugWithTimestamp(String.Format("Starting nStream.Read"));
                WriteDebugWithTimestamp(String.Format(String.Format("buffSize={0} -- inStream.Length={1}", buffSize, inStream.Length)));

                bytesRead = nStream.Read(inStream, 0, buffSize); //Recieve data from stream to inStream, return amount of bytes read

                WriteDebugWithTimestamp(String.Format("receiveMessage bytesread: {0}", bytesRead.ToString()));
                WriteDebugWithTimestamp(String.Format("receiveMessage client.Connected: {0}", client.Connected.ToString()));

                ../Cut
Run Code Online (Sandbox Code Playgroud)

客户是谁System.Net.Sockets.TcpClient.例外情况发生在nStream.Read.

Debian-6.0_64/Mono 2.11.2运行时输出为Mono --runtime=v4.0.30319 Program.exe:

receiveMessage obtaining client NetworkStream - daddy = 
receiveMessage client NetworkStream obtained, entering receive loop
receiveMessage this.excessData == null: True -- excessdata.length=n/a
Starting nStream.Read
buffSize=87380 -- inStream.Length=10025

System.ArgumentOutOfRangeException: Argument is out of range.
Parameter name: offset+size exceeds the size of buffer
  at System.Net.Sockets.NetworkStream.Read (System.Byte[] buffer, Int32 offset, Int32 size) [0x00000] in <filename unknown>:0 
  at SocketOperations.CSocketOperations.receiveMessage (System.String& recvStr, System.String daddy) [0x00000] in <filename unknown>:0 
  at SocketServerV3_Demo.CDownloadServer_ClientHandle..ctor (System.Net.Sockets.TcpClient client) [0x00000] in <filename unknown>:0 
  at SocketServerV3_Demo.Program.handleNewConnection (System.Net.Sockets.TcpClient client) [0x00000] in <filename unknown>:0 
Run Code Online (Sandbox Code Playgroud)

buffSize比字节数组长度大,但是当我在Windows上运行完全相同的程序时没有发生异常(没有单声道,没有尝试).是什么赋予了?我该如何解决这个问题?它是否像增加缓冲区大小一样简单,还是还有其他东西在进行?我问的原因(而不仅仅是尝试它)是因为我不知道发生了什么,我想确保我正确地完成它.

我想找出这种行为背后的原因,因为看到它就像这样,我希望它也会在Windows上崩溃.除非缓冲区的大小由操作系统和Windows确定,否则它小于/等于字节数组大小..任何人都可以解释一下吗?

Mar*_*lig 6

看起来Mono TcpClient.ReceiveBufferSize比Windows更大.

根据MSDN Docs,默认值为8192字节.

我刚刚检查了Mono的实现,它正在调用GetSocketOption()底层套接字,所以它使用的是操作系统的默认设置.

你有三个选择:

  1. 使用更改套接字的接收缓冲区大小client.ReceiveBufferSize = new_size.
  2. 分配足够大的缓冲区.
  3. 不要读取比缓冲区可容纳的数据更多的数据:

    var max_size = Math.Min (client.ReceiveBufferSize, buffer.Length);
    bytesRead = nStream.Read(inStream, 0, max_size);
    
    Run Code Online (Sandbox Code Playgroud)