問題を解決するために考えられるすべての方法を試しました。私の質問を説明します。
WCF NetTCP サービスを使用してファイル転送メカニズムを作成しようとしています。クライアントは、別のマシンで実行されているサービスからファイルを要求できます。ファイル転送は 3 段階で行われます。
BeginFileTranfer - サーバー側での操作。ファイルを開き、転送の準備をします。これにより、セッションが開始されます。
[OperationContract(IsInitiating = true, IsTerminating = false)]
string BeginFileTransfer(TrnsferType oType, string strFileName,string strFilePath);
GetFileData - サーバー側での操作で、開いているファイルから呼び出しごとに 1024 バイト (当面の間) を送信します
[OperationContract(IsInitiating = false, IsTerminating = false)]
CFileTransferData GetFileData(string strRequestId);
EndFileTransfer - サーバー側での操作で、ファイルを閉じます。セッションを終了します
[OperationContract(IsInitiating = false, IsTerminating = true)]
bool EndFileTranser(string strRequestId);
クライアント側では、関数を呼び出してリモート サービスからファイルを取得します
private void btnGet_Click(object sender, EventArgs e)
{
string strId = _AgentService.BeginFileTransfer(iVayagerAgent.TrnsferType.GET,"contacts.csv","D:");
iVayagerAgent.CFileTransferData oData = null;
FileStream oFile = null;
do
{
oData = _AgentService.GetFileData(strId);
if (oData.State == iVayagerAgent.TransferState.OPEN)
{
oFile = File.Create("C:\\123\\contacts.csv");
oFile.Write(oData.Data, 0, oData.Data.Length);
}
else if (oData.State == iVayagerAgent.TransferState.PENDING)
{
oFile.Write(oData.Data, 0, oData.Data.Length);
}
else
{
oFile.Close();
}
}while(oData.State != iVayagerAgent.TransferState.CLOSE);
}
iVayagerAgent.CFileTransferData
ファイルデータをクライアント側に送信するために使用されるクラスです
[DataContract]
public enum TransferState : int
{
[EnumMember]
OPEN = 0,
PENDING = 1,
CLOSE = 2
}
[DataContract]
public class CFileTransferData
{
[DataMember]
public TransferState State{get; set;}
[DataMember]
public byte[] Data;
[DataMember]
public string Status;
[DataMember]
public string StatusDescription;
}
ループで GetFileData を呼び出すと問題が発生します。GetFileData の最初の呼び出しは正常に機能します。次の後続の呼び出しで次のエラーが発生する
ソケット接続が中止されました。これは、メッセージの処理中にエラーが発生したか、リモート ホストが受信タイムアウトを超過したか、基になるネットワーク リソースの問題が原因である可能性があります。ローカル ソケットのタイムアウトは「00:00:59.9679982」でした。
これは、データを含むバイト配列を送信した場合にのみ発生します。その配列に何も送信しない場合、正常に動作します。私が調査できるいくつかの領域を指摘していただければ、それは素晴らしいことです。構成ファイルも表示します。
サーバー構成
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="iVoyagerAgentServiceBinding" receiveTimeout="00:30:00">
<security mode="None"></security>
<readerQuotas maxDepth="32"
maxStringContentLength="5242880"
maxArrayLength="2147483646"
maxBytesPerRead="4096"
maxNameTableCharCount="5242880" />
</binding>
</netTcpBinding>
</bindings>
<services>
<service name="iVayagerAgent.iVoyagerAgentService" behaviorConfiguration="">
<endpoint address="net.tcp://192.168.1.48:9020/IiVoyagerAgentService"
binding="netTcpBinding" bindingConfiguration="iVoyagerAgentServiceBinding" contract="iVayagerAgent.IiVoyagerAgentService" >
</endpoint>
</service>
</services>
</system.serviceModel>
</configuration>
クライアント構成(実行時にこれを行います。構成ファイルから構成を選択するのではありません)
EndpointAddress oEndPointAddress = new EndpointAddress("net.tcp://" + tbIP.Text + ":" + tbPort.Text + "/IiVoyagerAgentService");
NetTcpBinding oBinding = new NetTcpBinding();
oBinding.Name = "iVoyagerAgentServiceBinding";
XmlDictionaryReaderQuotas myReaderQuotas = new XmlDictionaryReaderQuotas();
myReaderQuotas.MaxStringContentLength = 5242880;
myReaderQuotas.MaxArrayLength = 2147483646;
myReaderQuotas.MaxBytesPerRead = 4096;
myReaderQuotas.MaxDepth = 32;
myReaderQuotas.MaxNameTableCharCount = 5242880;
oBinding.GetType().GetProperty("ReaderQuotas").SetValue(oBinding, myReaderQuotas, null);
oBinding.Security.Mode = SecurityMode.None;
oBinding.ReceiveTimeout = new TimeSpan(0,10,0);
_ChannelFactory = new ChannelFactory<iVayagerAgent.IiVoyagerAgentService>(oBinding, oEndPointAddress);
_ChannelFactory.Opened += new EventHandler(_ChannelFactory_Opened);
_ChannelFactory.Closed += new EventHandler(_ChannelFactory_Closed);
_ChannelFactory.Open();
_AgentService= _ChannelFactory.CreateChannel();
これは、GetFileData の応答を作成する関数です。
[DataContract]
public enum TransferState : int
{
[EnumMember]
OPEN = 0,
PENDING = 1,
CLOSE = 2
}
[DataContract]
public class CFileTransferData
{
[DataMember]
public TransferState State{get; set;}
[DataMember]
public byte[] Data;
[DataMember]
public string Status;
[DataMember]
public string StatusDescription;
}
public CFileTransferData Get()
{
int bNum = 0;
byte[] bData = new byte[BufferSize];
CFileTransferData oData = new CFileTransferData();
oData.Status = "1";
oData.StatusDescription = "Success";
try
{
if(Type == TrnsferType.GET)
{
bNum = File.Read(bData, 0, (Int32)BufferSize);
if (BytesRead == 0)
{
oData.State = TransferState.OPEN;
}
else
{
if (bNum != 0)
{
oData.State = TransferState.PENDING;
}
else
{
oData.State = TransferState.CLOSE;
}
}
oData.Data = bData;
BytesRead += bNum;
BytesToRead -= bNum;
}
else
{
oData.Status = "0";
oData.StatusDescription = "Invalid Transfer Type";
}
}
catch
{
oData.Status = "0";
oData.StatusDescription = "Critical Error";
}
return oData;
}
私が間違っているところを見つけるのを手伝ってください。前もって感謝します...