代码之家  ›  专栏  ›  技术社区  ›  Annonymus

C#-httpWebRequest流的大小是否有限制?

  •  2
  • Annonymus  · 技术社区  · 9 年前

    我正在尝试构建一个应用程序,它使用httpwebrequests从自定义Web服务器下载一个小的二进制文件(20-25KB)。

    这是服务器端代码:

    Stream UpdateRequest = context.Request.InputStream;
    byte[] UpdateContent = new byte[context.Request.ContentLength64];
    UpdateRequest.Read(UpdateContent, 0, UpdateContent.Length);
    String remoteVersion = "";
    for (int i = 0;i < UpdateContent.Length;i++) { //check if update is necessary
        remoteVersion += (char)UpdateContent[i];
    }
    
    byte[] UpdateRequestResponse;
    
    if (remoteVersion == remotePluginVersion) {
        UpdateRequestResponse = new byte[1];
        UpdateRequestResponse[0] = 0; //respond with a single byte set to 0 if no update is required
    } else {
        FileInfo info = new FileInfo(Path.Combine(Directory.GetCurrentDirectory(), "remote logs", "PointAwarder.dll"));
        UpdateRequestResponse = File.ReadAllBytes(Path.Combine(Directory.GetCurrentDirectory(), "remote logs", "PointAwarder.dll"));
        //respond with the updated file otherwise
    }
    
    //this byte is past the threshold and will not be the same in the version the client recieves
    Console.WriteLine("5000th byte: " + UpdateRequestResponse[5000]);
    
    //send the response
    context.Response.ContentLength64 = UpdateRequestResponse.Length;
    context.Response.OutputStream.Write(UpdateRequestResponse, 0, UpdateRequestResponse.Length);
    context.Response.Close();
    

    在此之后,数组UpdateRequestResponse包含整个文件,并已发送到客户端。

    客户端运行以下代码:

    //create the request
    WebRequest request = WebRequest.Create(url + "pluginUpdate");
    request.Method = "POST";
    //create a byte array of the current version
    byte[] requestContentTemp = version.ToByteArray();
    int count = 0;
    for (int i = 0; i < requestContentTemp.Length; i++) {
        if (requestContentTemp[i] != 0) {
            count++;
        }
    }
    byte[] requestContent = new byte[count];
    for (int i = 0, j = 0; i < requestContentTemp.Length; i++) {
        if (requestContentTemp[i] != 0) {
            requestContent[j] = requestContentTemp[i];
            j++;
        }
    }
    
    //send the current version
    request.ContentLength = requestContent.Length;
    Stream dataStream = request.GetRequestStream();
    dataStream.Write(requestContent, 0, requestContent.Length);
    dataStream.Close();
    
    //get and read the response
    WebResponse response = request.GetResponse();
    Stream responseStream = response.GetResponseStream();
    byte[] responseBytes = new byte[response.ContentLength];
    responseStream.Read(responseBytes, 0, (int)response.ContentLength);
    responseStream.Close();
    response.Close();
    
    //if the response containd a single 0 we are up-to-date, otherwise write the content of the response to file
    if (responseBytes[0] != 0 || response.ContentLength > 1) {
        BinaryWriter writer = new BinaryWriter(File.Open(Path.Combine(Directory.GetCurrentDirectory(), "ServerPlugins", "PointAwarder.dll"), FileMode.Create));
        writer.BaseStream.Write(responseBytes, 0, responseBytes.Length);
        writer.Close();
        TShockAPI.Commands.HandleCommand(TSPlayer.Server, "/reload");
    }
    

    发生这种情况是因为httpWebRequest有大小限制吗?我在代码中看不到任何可能导致此问题的bug,而在其他情况下,我只需要传递短数据序列(小于100字节),同样的代码也可以工作。

    MSDN页面没有提到这样的大小限制。

    2 回复  |  直到 9 年前
        1
  •  5
  •   Patrick Bell    9 年前

    这并不是说它有任何人为限制,这是 Streaming 你尝试做的事情的性质。我有一种感觉,下面这句话就是冒犯者:

    responseStream.Read(responseBytes, 0, (int)response.ContentLength);
    

    我以前遇到过这个问题(对于TCP流),它不会读取数组的所有内容,因为它们还没有全部通过网络发送。这就是我要尝试的。

    for (int i = 0; i < response.ContentLength; i++)
    {
       responseBytes[i] = responseStream.ReadByte();
    }
    

    编辑

    BinaryReader 基于的解决方案效率更高。以下是相关的解决方案:

    BinaryReader binReader = new BinaryReader(responseStream);
    const int bufferSize = 4096;
    byte[] responseBytes;
    using (MemoryStream ms = new MemoryStream())
    {
        byte[] buffer = new byte[bufferSize];
        int count;
        while ((count = binReader.Read(buffer, 0, buffer.Length)) != 0)
            ms.Write(buffer, 0, count);
        responseBytes = ms.ToArray();
    }
    
        2
  •  2
  •   usr    9 年前

    你是在假设 Read 正在读取您请求的字节数。但请求的计数只是一个上限。你必须容忍阅读小块内容。

    你可以使用 var bytes = new BinaryReader(myStream).ReadBytes(count); 来读取精确的数字。不要打电话 ReadByte 太频繁了,因为这是非常CPU密集型的。

    最好的解决方案是远离手册 HttpWebRequest 和使用 HttpClient WebClient byte[] .

    推荐文章