【问题标题】:WCF net.tcp only service giving TargetInvocationException/ServiceModel.CommunicationExceptionWCF net.tcp 仅提供 TargetInvocationException/ServiceModel.CommunicationException 的服务
【发布时间】:2010-10-05 19:00:23
【问题描述】:

我正在编写一个 WCF (net.tcp) 文件传输服务,该服务最终会将文件拆分为多个部分,并将这些部分从服务器/服务传输到客户端。目前客户端和服务器是控制台应用程序。

在编写此服务时,我多次遇到以下异常;

System.ServiceModel.CommunicationException:套接字连接已中止。这可能是由于处理您的消息时出错或远程主机超出接收超时,或者是潜在的网络资源问题引起的。本地套接字超时为“01:59:59.4220000”。

其实一开始是Unhandled Exception: System.Reflection.TargetInvocationException: 操作过程中发生异常,导致结果无效。检查 InnerException 以获取异常详细信息。 ---> 那么上面的 CommunicationException 文本就在这里。

按照典型的 Microsoft 方式,该异常消息毫无帮助,因此我终于向社区呼吁,看看我是否可以解决这个问题。

此外,如果这很重要,客户端将异步调用服务的两个方法( InitGetFilePart() 和 GetFilePart() )。根据我的日志,对 InitGetFilePartAsync(1, 1) 的第一次调用会一直处理到最后;这意味着它的“已完成”处理程序被调用,该处理程序又调用 vcClient.GetFilePartAsync(FileXferCargo, 1),然后它的处理程序产生一个 BackgroundWorker 线程 (workers[chunkNum]. RunWorkerAsync(cargoHolder[chunkNum] where chunkNum=1) 本身完成。这是我得到上述 TargetInvocationException 的时间。

过去我对 App.config 进行了各种调整(遗憾的是,我不记得具体是什么)以消除此异常,但现在我所做的任何事情似乎都没有任何区别,我只是不明白为什么会一直这样。

我已阅读有关此问题的其他建议,包括“您必须在客户端捕获异常,中止当前代理并创建并打开新代理。”好吧,我试过了,但我似乎无法捕捉到这个异常。

我还读到这可能是由于通过网络发送了太多数据,但是当我尝试发送我的小 4k 测试文件时,我得到了同样的异常。在我的调查中,我还读到我可以调用 1 个 WCF 服务函数/方法,多次使用带有 UserState 参数的 *Async() 调用,我正在这样做。

我承认在 WCF 方面我是一个相对的 n00b,但我很确定我的配置文件设置正确,适合我正在尝试做的事情。

这里是客户端和服务器 app.config 文件、服务接口定义和服务实现类的顶部。

客户端的 App.config:

<system.serviceModel>

    <bindings>
        <netTcpBinding>
            <binding name="MyTcpBinding_IFileXferService"
                     receiveTimeout="02:00:00"
                     sendTimeout="02:00:00"
                     transferMode="Streamed"
                     maxBufferSize="65536"
                     maxReceivedMessageSize="2147483647">
                <readerQuotas maxStringContentLength="2147483647"
                              maxArrayLength="2147483647"
                              maxBytesPerRead="65536" />
                <security mode="Transport">
                    <transport clientCredentialType="None">
                        <extendedProtectionPolicy policyEnforcement="Never" />
                    </transport>
                </security>
            </binding>
        </netTcpBinding>
    </bindings>

    <behaviors>
        <endpointBehaviors>
            <behavior name="ClientConfigBehavior">
                <dataContractSerializer maxItemsInObjectGraph="2147483647" />

                <clientCredentials>
                    <serviceCertificate>
                        <authentication certificateValidationMode="None" />
                    </serviceCertificate>
                </clientCredentials>

            </behavior>
        </endpointBehaviors>
    </behaviors>

    <client>
        <endpoint name="ClientConfig"
                  behaviorConfiguration="ClientConfigBehavior"
                  binding="netTcpBinding"
                  bindingConfiguration="MyTcpBinding_IFileXferService"
                  contract="ServiceRefs.IFileXferService" />
    </client>

</system.serviceModel>

服务器的 App.config:

    <bindings>
        <netTcpBinding>
            <!-- Under <netTcpBinding> setting the listenBacklog, 
                maxConnections, and maxBuffer* values high -->
            <binding name="MyTcpBinding_IFileXferService"
                 receiveTimeout="02:00:00"
                 sendTimeout="02:00:00"
                 openTimeout="00:01:00"
                 transferMode="Streamed"
                 portSharingEnabled="true"
                 listenBacklog="32"
                 maxConnections="64"
                 maxBufferSize="65536"
                 maxReceivedMessageSize="2147483646">
                <security mode="Transport">
                    <transport clientCredentialType="None" />
                </security>
            </binding>
        </netTcpBinding>

    </bindings>

    <services>
        <service name="MediaServer.LNMediaServerSvc"
                 behaviorConfiguration="ServerConfigBehavior">
            <host>
                <baseAddresses>
                    <add baseAddress="net.tcp://lngsead148191a:9000/fileXferSvc"/>
                </baseAddresses>
            </host>
            <endpoint name="mainEndPoint"
                      binding="netTcpBinding"
                      bindingConfiguration="MyTcpBinding_IFileXferService"
                      contract="ServiceInterfaces.IFileXferService" />
        </service>
    </services>

    <behaviors>
        <serviceBehaviors>
            <behavior name="ServerConfigBehavior">
                <serviceDebug includeExceptionDetailInFaults="true"/>
                <serviceThrottling maxConcurrentCalls="64" />
                <dataContractSerializer maxItemsInObjectGraph="2147483646" />
                <serviceCredentials>
                    <serviceCertificate findValue="tp_value"
                                        x509FindType="FindByThumbprint" />
                </serviceCredentials>
            </behavior>
        </serviceBehaviors>
    </behaviors>

</system.serviceModel>

Service接口定义如下;

[DataContract(IsReference = true)]
public class FileData
{
    private long m_startPos;

    [DataMember]
    public long StartPosition
    {
        get { return m_startPos; }
        set { m_startPos = value; }
    }

    private long m_endPos;

    [DataMember]
    public long EndPosition
    {
        get { return m_endPos; }
        set { m_endPos = value; }
    }

    private byte m_chunkNumber;

    [DataMember]
    public byte ChunkNumber
    {
        get { return m_chunkNumber; }
        set { m_chunkNumber = value; }
    }

    private long m_chunkSize;

    [DataMember]
    public long ChunkSize
    {
        get { return m_chunkSize; }
        set { m_chunkSize = value; }
    }

    private string md5Hash;

    [DataMember]
    public string MD5Hash
    {
        get { return md5Hash; }
        set { md5Hash = value; }
    }

    private string m_destFileSpec;

    [DataMember]
    public string DestinationFileSpec
    {
        get { return m_destFileSpec; }
        set { m_destFileSpec = value; }
    }

    private string m_srcFileSpec;

    [DataMember]
    public string SourceFileSpec
    {
        get { return m_srcFileSpec; }
        set { m_srcFileSpec = value; }
    }

    private Stream m_sourceStream;

    [DataMember]
    public Stream SourceStream
    {
        get { return m_sourceStream; }
        set { m_sourceStream = value; }
    }

    private UInt32 m_JobNo;

    [DataMember]
    public UInt32 JobNumber
    {
        get { return m_JobNo; }
        set { m_JobNo = value; }
    }

    private UInt32 m_fileNumber;

    [DataMember]
    public UInt32 FileNumber
    {
        get { return m_fileNumber; }
        set { m_fileNumber = value; }
    }

    private long m_fileSize;

    [DataMember]
    public long FileSize
    {
        get { return m_fileSize; }
        set { m_fileSize = value; }
    }
}


[DataContract]
public partial class FileXferCargo
{
    private FileData m_fileData;

    [DataMember]
    public FileData FileData
    {
        get { return m_fileData; }
        set { m_fileData = value; }
    }


    private bool m_cancelled;

    [DataMember]
    public bool Cancelled
    {
        get { return m_cancelled; }
        set { m_cancelled = value; }
    }

    private long m_errorCode;

    [DataMember]
    public long ErrorCode
    {
        get { return m_errorCode; }
        set { m_errorCode = value; }
    }

    private Exception m_exceptionObj;

    [DataMember]
    public Exception Exception
    {
        get { return m_exceptionObj; }
        set { m_exceptionObj = value; }
    }
}


[ServiceContract]
public interface IFileXferService
{
    [OperationContract]
    bool InitFileRequest(ref FileXferCargo fileRequest);

    [OperationContract]
    bool InitGetFilePart(ref FileXferCargo fileCargo);

    [OperationContract]
    Stream GetFilePart(FileXferCargo fileCargo);

    [OperationContract]
    int CloseFile(FileData fileData);
}

Service实现类定义如下;

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, 
    ConcurrencyMode = ConcurrencyMode.Multiple,
    UseSynchronizationContext = false)
]
public class LNMediaServerSvc : IFileXferService
{
    ...
}

【问题讨论】:

  • 在服务和客户端上开启 WCF 跟踪:msdn.microsoft.com/en-us/library/ms733025.aspx
  • 在基于 HTTP 的托管的情况下,问题将很明显 - FileData 包含 Stream。在 Net.Tcp 中,我不确定这是否允许。
  • 该 Stream 成员仅用于“本地”在几个方法之间携带 Stream。不久前我发现我无法以这种方式返回流,因此有 2 个 Init 方法,然后是 GetFilePart,它是返回实际 Stream 的方法。
  • 但流仍然作为 DataMember 包含在 DataContract 中,在 OperationContract 中用作参数。
  • 啊,好吧,我要把它拿出来,看看这是否一直是我的问题。

标签: wcf sockets net.tcp


【解决方案1】:

对于您的 netTcpBinding,在客户端和服务器配置文件中将安全模式设置为无:

<security mode="None" />

这是一个快速修复。

如果您需要为 netTcpBinding 启用安全性,那么您必须实现委托和模拟。

在此处阅读更多信息:http://msdn.microsoft.com/en-us/library/ms730088.aspx

根据我的阅读和谷歌搜索,这是一个多跳模拟问题。模拟只能延续到一跳。通过将安全模式设置为无,您可以在调用 WCF 服务时阻止身份验证步骤。

【讨论】:

    【解决方案2】:

    没有评论按钮了,所以我把它放在这里。是的,我已经打开了跟踪,但似乎我需要阅读一本书才能了解跟踪数据试图告诉我的所有内容。也就是说,我查看了跟踪信息,我看不到的一件事是导致套接字中止的任何事情。只是似乎无缘无故地发生。 :(

    【讨论】:

      【解决方案3】:

      对我来说,这是因为托管 WCF 的服务器的 web.config 中没有 net.tcp 绑定。当我为服务添加相同的绑定时,我没有得到异常。因此,如果 Web 和 WCF 托管在不同的服务器中,则需要在双方都有绑定。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-22
        • 2011-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-11
        • 2011-02-06
        • 1970-01-01
        相关资源
        最近更新 更多