1

問題を解決するために考えられるすべての方法を試しました。私の質問を説明します。

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;
}

私が間違っているところを見つけるのを手伝ってください。前もって感謝します...

4

1 に答える 1

2

私を助けようと努力してくれた asafrob と、友人の Roshen に感謝ます。何日もコーディングを行った後、どこが間違っているのかを理解できるようになりました。最後に[EnumMembers]で起こっています

[DataContract]
public enum TransferState : int
{
    [EnumMember]
    OPEN = 0,
    PENDING = 1,
    CLOSE = 2
}

応答で PENDING および CLOSE Enum メンバーを使用している場合、この宣言は間違っています。PENDING および CLOSE メンバーを [EnumMembers] として言及していないため、シリアル化プロセスで例外がスローされます。メンバーを使用している場合は、それを宣言する必要があります。シリアル化プロセスがスムーズになります。

これは正しい形式です... (これはすべて、基礎が欠けているためです:D)

[DataContract]
public enum TransferState : int
{
    [EnumMember]
    OPEN = 0,
    [EnumMember]
    PENDING = 1,
    [EnumMember]
    CLOSE = 2
}

私の質問では、シナリオを話しました。これで、なぜそのように振る舞うかを説明できます。 ループで GetFileData を呼び出すと問題が発生します。GetFileData の最初の呼び出しは正常に機能します。次の後続の呼び出しで次のエラーが発生する

最初の呼び出しで機能する理由は、属性を [EnumMember] として言及した OPEN enum であるため、通常どおりシリアル化して正常に動作し、次の呼び出しで応答ステータスを PENDING に設定します。これにより、シリアル化の問題が発生します。

皆様のご支援とスタックオーバーフローに心から感謝いたします。これが他の多くの人に役立つことを願っています。

-ヴェヌーラ

于 2013-08-22T04:40:52.520 に答える