我尝试了所有可能的方法来解决我的问题。我会解释我的问题。
我正在尝试使用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;
}
请帮我找出错误的地方。提前谢谢你......
答案 0 :(得分: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工作正常。下一个后续调用会出现以下错误
为什么它在第一次调用时工作是,OPEN枚举我已经提到属性为[EnumMember] 所以它得到正常序列化并正常工作,下次调用我将响应状态设置为PENDING。这导致序列化问题。
非常感谢您的所有支持和stackoverflow。希望这会对其他许多人有所帮助。
-Venura