1

我尝试了所有可能的方法来解决我的问题。我会解释我的问题。

我正在尝试使用 WCF NetTCP 服务创建文件传输机制。客户端可以向在另一台机器上运行的服务请求文件。文件传输分三个阶段进行。

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 枚举成员,则此声明是错误的。因为我们没有提到 PENDING 和 CLOSE 成员为 [EnumMembers],所以在序列化过程中它出去并抛出异常。如果您使用任何成员,则必须声明它。它将使序列化过程顺利。

这是正确的格式...(这都是因为缺乏基础知识:D)

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

在我的问题中,我讲述了这个场景。现在我可以解释它为什么会这样。 当我在循环中调用 GetFileData 时出现问题。第一次调用 GetFileData 工作正常。下一个后续调用给出以下错误

为什么它在第一次调用中起作用是,OPEN enum 我已经将属性提到为 [EnumMember] 所以它可以正常序列化它并且工作正常,下一次调用我将响应状态设置为 PENDING。这会导致序列化问题。

因此,非常感谢您对 stackoverflow 的所有支持。希望这会对其他人有所帮助。

-维努拉

于 2013-08-22T04:40:52.520 回答