WCF を使用してファイル ストレージを作成することを考えました。インターネットで検索し、多くの例を見つけて、彼のサービスを作成しました。
namespace CTFileStorage
{
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
interface CTIFileStorageClass
{
[OperationContract]
CTFileName UploadStream(CTRemoteFileInfo faInfo);
}
[MessageContract]
public class CTRemoteFileInfo : IDisposable
{
[MessageHeader(MustUnderstand = true)]
public string FileName;
[MessageHeader(MustUnderstand = true)]
public long Length;
[MessageBodyMember(Order = 1)]
public System.IO.Stream FileByteStream;
public void Dispose()
{
if (FileByteStream != null)
{
FileByteStream.Close();
FileByteStream = null;
}
}
}
[MessageContract]
public class CTFileName
{
[MessageHeader(MustUnderstand = true)]
public string FileName;
}
public class CTFileStorageClass : CTIFileStorageClass
{
public CTFileName UploadStream(CTRemoteFileInfo faFileInfo)
{
try
{
Guid guid = Guid.NewGuid();
FileStream targetStream = null;
Stream sourceStream = faFileInfo.FileByteStream;
string uploadFolder = @"D:\Storage\";
string[] paths=faFileInfo.FileName.Split('.');
string path=null;
if (paths.Length>=2)
{
path="."+paths[paths.Length-1];
}
string filePath = Path.Combine(uploadFolder, guid.ToString()+path);
using (targetStream = new FileStream(filePath, FileMode.Create,
FileAccess.Write, FileShare.None))
{
//read from the input stream in 65000 byte chunks
const int bufferLen = 65000;
byte[] buffer = new byte[bufferLen];
int count = 0;
while ((count = sourceStream.Read(buffer, 0, bufferLen)) > 0)
{
// save to output stream
targetStream.Write(buffer, 0, count);
Thread.Sleep(10);
}
targetStream.Close();
sourceStream.Close();
}
CTFileName fileName = new CTFileName() { FileName = guid.ToString() };
return fileName;
}
catch
{
return null;
}
}
}
}
Windows service.app.config サービスでホストされる WCF:`
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="binding" openTimeout="04:00:00" sendTimeout="04:00:00" receiveTimeout="04:00:00" closeTimeout="04:00:00"
allowCookies="true" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<!-- This section is optional with the new configuration model
introduced in .NET Framework 4. -->
<service name="CTFileStorage.CTFileStorageClass"
behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ServiceModelSamples/service"/>
</baseAddresses>
</host>
<!-- this endpoint is exposed at the base address provided by host: http://localhost:8000/ServiceModelSamples/service -->
<endpoint address=""
binding="basicHttpBinding" bindingConfiguration="binding"
contract="CTFileStorage.CTIFileStorageClass" />
<!-- the mex endpoint is exposed at http://localhost:8000/ServiceModelSamples/service/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceDebug includeExceptionDetailInFaults="False"/>
<serviceThrottling
maxConcurrentCalls="1000"
maxConcurrentSessions="1000"
maxConcurrentInstances="1000"
/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>`
負荷をモデル化するには、クライアント コンソール アプリケーションを作成します。
static void Main(string[] args)
{
Thread thread = new Thread(new ParameterizedThreadStart(Copy));
thread.Start("D:\\toad10513\\toad10513.rar");
Thread thread1 = new Thread(new ParameterizedThreadStart(Copy));
thread1.Start("D:\\toad10513\\toad105131.rar");
Thread thread2 = new Thread(new ParameterizedThreadStart(Copy));
thread2.Start("D:\\toad10513\\toad105132.rar");
Thread thread3 = new Thread(new ParameterizedThreadStart(Copy));
thread3.Start("D:\\toad10513\\toad105133.rar");
Thread thread4 = new Thread(new ParameterizedThreadStart(Copy));
thread4.Start("D:\\toad10513\\toad105134.rar");
Thread thread5 = new Thread(new ParameterizedThreadStart(Copy));
thread5.Start("D:\\toad10513\\toad105135.rar");
}
private static void Copy(object faFile)
{
string s = faFile as string;
if (s != null)
{
StorageClient.Storage.CTIFileStorageClassClient client = new Storage.CTIFileStorageClassClient();
Stream sw = File.Open(s, FileMode.Open);
Console.WriteLine(faFile.ToString());
client.UploadStream(ref s, sw.Length, sw);
sw.Close();
}
}
}
}
このアプリケーションは、ストレージにアップロードします。別のスレッドでは、ファイル サイズは 400 MB です。1 つのスレッドのアップロードを使用している場合は、正常に終了します。しかし、6 つのスレッドを開始すると、それは 3 つのスレッドしか動作せず、他のスレッドは遅れます。そして、何分かの作業の後、「接続ソケットに失敗しました」という例外が発生します。