我的目标是在没有打开传入端口的防火墙后到达WCF服务。 我选择的解决方案是在公共端托管一个双工WCF服务,它具有与没有涉及防火墙时使用的相同合同作为回调。
如果我使用netTcpBinding,但是因为我需要流式通信,所以我必须使用自定义绑定。
在我启动防火墙之前,一切正常。此时,直接调用(从防火墙后面出来)工作正常,但回调没有(防火墙阻止它)。
问题是为什么?他们不会使用与预定义的netTcpBinding相同的频道吗?
这是我在app.config中的频道堆栈:
<customBinding>
<binding name="ReversedServiceBinding">
<compositeDuplex />
<oneWay />
<binaryMessageEncoding />
<tcpTransport transferMode="Streamed" />
</binding>
</customBinding>
答案 0 :(得分:2)
实际行为是正确的。您已经使用了compositeDuplex绑定元素 - 复合词的含义正是您所获得的 - 两个独立的通道,每个通道都用于一个方向。仅对于默认情况下不支持双工通信的传输信道,仅需要复合双工。 TCP传输通道不是这种情况 - 检查remarks。如果你不使用compositeDuplex,它应该像你期望的那样工作。此外,无需定义全新的自定义绑定以允许流式传输。 NetTcpBinding还具有TransportMode属性,可以在配置中指定。
修改强> 我已经准备好了Net.TCP双工通信的工作实例。它不使用流媒体。您使用双工TCP通信时无法进行流式传输。您可以尝试将双工通信与分块通道结合使用,或选中WCF Xtensions(商业产品)。
共享合同
namespace NetTcpDuplexContracts
{
[ServiceContract(SessionMode = SessionMode.Required,
CallbackContract = typeof(IDuplexServiceCallback))]
public interface IDuplexService
{
[OperationContract(IsOneWay = true)]
void DoAction(string message);
}
public interface IDuplexServiceCallback
{
[OperationContract(IsOneWay = true)]
void ConfirmAction(string message);
}
}
服务和主持人
namespace NetTcpDuplexService
{
public class DuplexService : IDuplexService
{
public void DoAction(string message)
{
Console.WriteLine("DoAction: " + message);
var callbackChannel =
OperationContext.Current.GetCallbackChannel<IDuplexServiceCallback>();
callbackChannel.ConfirmAction("Ping back " + message);
}
}
class Program
{
public static void Main(string[] args)
{
try
{
using (var host = new ServiceHost(typeof(DuplexService)))
{
host.Open();
Console.ReadLine();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
}
}
服务配置
<configuration>
<system.serviceModel>
<services>
<service name="NetTcpDuplexService.DuplexService">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8800/NetTcpDuplexService"/>
</baseAddresses>
</host>
<endpoint address="" binding="netTcpBinding" contract="NetTcpDuplexContracts.IDuplexService" />
</service>
</services>
</system.serviceModel>
</configuration>
回调和客户
namespace NetTcpDuplexClient
{
public class DuplexServiceCallback : IDuplexServiceCallback
{
public void ConfirmAction(string message)
{
Console.WriteLine(message);
}
}
class Program
{
public static void Main(string[] args)
{
DuplexChannelFactory<IDuplexService> factory = null;
try
{
var callbackService = new DuplexServiceCallback();
var context = new InstanceContext(callbackService);
factory = new DuplexChannelFactory<IDuplexService>(context, "IDuplexService_NetTcp");
var channel = factory.CreateChannel();
channel.DoAction("Hello world");
factory.Close();
Console.ReadLine();
}
catch (Exception e)
{
if (factory != null && factory.State != CommunicationState.Closed)
{
factory.Abort();
}
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
}
}
客户端配置
<configuration>
<system.serviceModel>
<client>
<endpoint name="IDuplexService_NetTcp" address="net.tcp://localhost:8800/NetTcpDuplexService" binding="netTcpBinding"
contract="NetTcpDuplexContracts.IDuplexService" />
</client>
</system.serviceModel>
</configuration>