Как я могу ускорить буферизованный перевод WCF?

1

Я использую схему Buffered transferMode в WCF для переноса заархивированного файла с сервера на клиента. Передача происходит в обратном вызове, и файлы размером 3,7 мегабайта занимают чуть более 2 минут для передачи. Поскольку у меня есть много других функций, работающих с использованием этого буферизованного режима, я бы предпочел не менять схему.

Для справки здесь используются привязки, которые я использую

<bindings>
  <netTcpBinding>
    <binding name="NetTcpBinding_MyIIService"
      closeTimeout="00:01:00"
      openTimeout="00:01:00"
      receiveTimeout="00:10:00"
      sendTimeout="00:01:00"
      transactionFlow="false"
      transferMode="Buffered"
      transactionProtocol="OleTransactions"
      hostNameComparisonMode="StrongWildcard"
      listenBacklog="10"
      maxBufferPoolSize="4967294"
      maxBufferSize="4967294"
      maxConnections="10"
      maxReceivedMessageSize="104857600">
      <readerQuotas maxDepth="104857600"
             maxStringContentLength="104857600"
             maxArrayLength="104857600"
             maxBytesPerRead="104857600"
             maxNameTableCharCount="104857600"/>
      <reliableSession ordered="true"
             inactivityTimeout="20:00:10"
             enabled="true"/>
      <security mode="None">
        <transport clientCredentialType="Windows"
             protectionLevel="EncryptAndSign"/>
        <message clientCredentialType="Windows"/>
      </security>
    </binding>
  </netTcpBinding>
</bindings> 

Я уже пробовал несколько разных вариантов размеров, которые, похоже, не имеют значения, если они не настроены на небольшие.

В обратном вызове на сервере я использую следующий фрагмент для отправки двоичных (zip) файлов клиенту. Здесь я конвертирую zip файл в ASCII, используя кодировку Base64. (Кстати, передача zip файла в виде двоичного файла выполняется в одно и то же время, но приносит повреждение)

byte[] binaryData;
System.IO.FileStream inFile;
inFile = new System.IO.FileStream(path2ZipFile,
             System.IO.FileMode.Open,
             System.IO.FileAccess.Read);
binaryData = new Byte[inFile.Length];
            long bytesRead = inFile.Read(binaryData, 0, (int)inFile.Length);
inFile.Close();
string convertedToBase64 = System.Convert.ToBase64String(binaryData, 0,
                           binaryData.Length);
handler(guest, zipFilename, convertedToBase64);

Чтобы удалить файл на мой общий ресурс Google Диска, требуется около 15 секунд. так что. Как я могу улучшить свою скорость передачи?

Теги:
performance
wcf
nettcpbinding

1 ответ

2

Я пробовал все остальное, вы могли бы дать сжатие. В двух словах, для сжатия данных на стороне хоста, требуется 1/2 секунды, чтобы выполнить распаковку на стороне клиента, но вы уменьшите общую полезную нагрузку, отправленную по проводу примерно на 1/3.

Вы можете сжать массив byte(), прежде чем изменять его на строку с помощью System.Convert.ToBase64String или вы можете сжать строку base64 перед отправкой. Здесь немного класса сжатия/распаковки для С#:

using System;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace CompressString
{
internal static class StringCompressor
{
    /// <summary>
    /// Compresses the string.
    /// </summary>
    /// <param name="text">The text.</param>
    /// <returns></returns>
    public static string CompressString(string text)
    {
        byte[] buffer = Encoding.UTF8.GetBytes(text);
        var memoryStream = new MemoryStream();
        using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true))
        {
            gZipStream.Write(buffer, 0, buffer.Length);
        }

        memoryStream.Position = 0;

        var compressedData = new byte[memoryStream.Length];
        memoryStream.Read(compressedData, 0, compressedData.Length);

        var gZipBuffer = new byte[compressedData.Length + 4];
        Buffer.BlockCopy(compressedData, 0, gZipBuffer, 4, compressedData.Length);
        Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gZipBuffer, 0, 4);
        return Convert.ToBase64String(gZipBuffer);
    }

    /// <summary>
    /// Decompresses the string.
    /// </summary>
    /// <param name="compressedText">The compressed text.</param>
    /// <returns></returns>
    public static string DecompressString(string compressedText)
    {
        byte[] gZipBuffer = Convert.FromBase64String(compressedText);
        using (var memoryStream = new MemoryStream())
        {
            int dataLength = BitConverter.ToInt32(gZipBuffer, 0);
            memoryStream.Write(gZipBuffer, 4, gZipBuffer.Length - 4);

            var buffer = new byte[dataLength];

            memoryStream.Position = 0;
            using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
            {
                gZipStream.Read(buffer, 0, buffer.Length);
            }

            return Encoding.UTF8.GetString(buffer);
        }
    }
}
}

Удачи тебе. Я нашел эту утилиту сжатия быстрой и простой в использовании. Конечно, этот код работает только в том случае, если вы используете.NET на обоих концах. Если у вас есть клиент iOS или Android, вам нужно будет использовать утилиту сжатия, нейтральную для ОС.

  • 0
    Или просто включите сжатие в net.tcp, если вы используете .net 4.5. Также OP упоминается с использованием net.tcp, таким образом .net.
  • 0
    @ Брайан - Да, я использую .net 4.0 с обеих сторон. Большое спасибо за этот пример. Я попробую это завтра, когда позволит время, и я перезвоню вам. @ Арон, спасибо за твои предложения
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню