WCF 托管、配置和连接地址/端口问题(包括 Delphi 7 客户端)
我有一个 WCF 服务(MyWCFService),其基地址
http://localhost:8732/Design_Time_Addresses/MyWCFService/Service1/
和 app.config 中的以下内容
<system.serviceModel>
<diagnostics performanceCounters="Default">
<messageLogging logEntireMessage="true" logMalformedMessages="true"
logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<extensions>
<behaviorExtensions>
<add name="wsdlExtensions" type="WCFExtras.Wsdl.WsdlExtensionsConfig, WCFExtras, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<services>
<service name="MyWCFService.Service1" behaviorConfiguration="MyWCFService.Service1Behavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/MyWCFService/Service1/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<!--<endpoint address ="" binding="wsHttpBinding" contract="MyWCFService.IService1">
--><!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
--><!--
<identity>
<dns value="localhost"/>
</identity>
</endpoint>-->
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="" binding="basicHttpBinding" behaviorConfiguration="singleFileEndpointBehavior" contract="MyWCFService.IService1"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="singleFileEndpointBehavior">
<wsdlExtensions singleFile="True" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyWCFService.Service1Behavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
此 MyWCFService 托管在 WinForms 应用程序(WinFormsServiceHost)中,其基地址
net.tcp://localhost:2202/Service1
和 WinForm 上的以下代码
namespace MyWCFService
{
public partial class Form1 : Form
{
bool serviceStarted = false;
ServiceHost myServiceHost = null;
Uri baseAddress = new Uri("net.tcp://localhost:2202/Service1");
NetTcpBinding binding = new NetTcpBinding();
public Form1() { InitializeComponent(); }
private void StartService(object sender, EventArgs e)
{
if (!serviceStarted)
{
myServiceHost = new ServiceHost(typeof(Service1), baseAddress);
myServiceHost.AddServiceEndpoint(typeof(IService1), binding, baseAddress);
myServiceHost.Open();
serviceStarted = true;
RefreshServiceStatus(this, null);
}
}
private void RefreshServiceStatus(object sender, EventArgs e) ...
private void StopService(object sender, EventArgs e) ...
}
}
我使用 WCF 测试客户端(WinFormsWCFTester)测试此服务),它
net.tcp://localhost:2202/Service1
在 WinForm 上使用并具有以下代码
namespace MyWCFService
{
public partial class Form1 : Form
{
IService1 IService1 = null;
public Form1() { InitializeComponent(); }
private void Form1_Load(object sender, EventArgs e)
{
EndpointAddress address = new EndpointAddress(new Uri("net.tcp://localhost:2202/Service1"));
NetTcpBinding binding = new NetTcpBinding();
ChannelFactory<IService1> factory = new ChannelFactory<IService1>(binding, address);
IService1 = factory.CreateChannel();
}
private void btnTest_Click(object sender, EventArgs e)
{
lblResponse.Text = IService1.GetData(txtSomeText.Text);
}
}
}
我还有一个 Delphi 7 测试客户端 (Delphi7WCFTester),它使用地址
http://localhost:8732/Design_Time_Addresses/MyWCFService/Service1/
注意:该地址来自当我的 WinFormsServiceHost 运行时添加服务引用生成的 WSDL。我使用更新的 WSDL Importer 为 Delphi 7 创建 Pascal 代理类。
我的 PC 上的情况(当我将代码移动到另一台 PC 或更糟的情况下,甚至会发生更奇怪的事情 - 例如,VM!)
当服务运行时(由WCF 服务主机 - 由 VS2010 调用的 WcfSvcHost.exe),Web 浏览器可以导航到
http://localhost:8732/Design_Time_Addresses/MyWCFService/Service1/
并且 telnet 可以连接到本地主机 8732。我的 Delphi 客户端 (Delphi7WCFTester) 可以连接并正常工作,但我的 WCF 客户端 (WinFormsWCFTester) 无法连接(异常消息“Could”无法连接到 net.tcp://localhost:2202/Service1 ... TCP 错误代码 10061 ... 目标计算机主动拒绝它 127.0.0.1:2202")
当服务由我的 WinFormsServiceHost 托管并在 Visual Studio 中运行时调试器,Web浏览器可以导航到 http://localhost:8732/Design_Time_Addresses/MyWCFService/Service1/ telnet 可以连接到端口 8732 或 2202。两个客户端(WinFormsWCFTester 和 Delphi7WCFTester)都可以连接并正常工作。
当服务由 WinFormsServiceHost 托管并作为 exe 独立运行时(我使用 VS2010 中的 Ctrl-F5),这两个地址都无法使用 Webbrowser 浏览。 Telnet 可以连接到 2202,但不能连接到 8732。我的 WinFormsWCFTester 客户端可以连接并正常工作,但我的 Delphi7WCFTester 无法连接。
我的问题
正如您可能从我对我的情况的详尽描述中看出的那样,我有点迷失了。我需要一些指导来重新控制正在发生的事情。无论服务如何托管,两个客户端都应该连接并正常工作。我知道我还有很多东西要学。我希望有人能通过一些重要的指示引导我走向正确的方向。
I have a WCF service (MyWCFService) with base address
http://localhost:8732/Design_Time_Addresses/MyWCFService/Service1/
and the following in app.config
<system.serviceModel>
<diagnostics performanceCounters="Default">
<messageLogging logEntireMessage="true" logMalformedMessages="true"
logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<extensions>
<behaviorExtensions>
<add name="wsdlExtensions" type="WCFExtras.Wsdl.WsdlExtensionsConfig, WCFExtras, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<services>
<service name="MyWCFService.Service1" behaviorConfiguration="MyWCFService.Service1Behavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/MyWCFService/Service1/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<!--<endpoint address ="" binding="wsHttpBinding" contract="MyWCFService.IService1">
--><!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
--><!--
<identity>
<dns value="localhost"/>
</identity>
</endpoint>-->
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="" binding="basicHttpBinding" behaviorConfiguration="singleFileEndpointBehavior" contract="MyWCFService.IService1"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="singleFileEndpointBehavior">
<wsdlExtensions singleFile="True" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyWCFService.Service1Behavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
This MyWCFService is hosted in a WinForms app (WinFormsServiceHost) with base address
net.tcp://localhost:2202/Service1
and the following code on a WinForm
namespace MyWCFService
{
public partial class Form1 : Form
{
bool serviceStarted = false;
ServiceHost myServiceHost = null;
Uri baseAddress = new Uri("net.tcp://localhost:2202/Service1");
NetTcpBinding binding = new NetTcpBinding();
public Form1() { InitializeComponent(); }
private void StartService(object sender, EventArgs e)
{
if (!serviceStarted)
{
myServiceHost = new ServiceHost(typeof(Service1), baseAddress);
myServiceHost.AddServiceEndpoint(typeof(IService1), binding, baseAddress);
myServiceHost.Open();
serviceStarted = true;
RefreshServiceStatus(this, null);
}
}
private void RefreshServiceStatus(object sender, EventArgs e) ...
private void StopService(object sender, EventArgs e) ...
}
}
I test this service with a WCF test client (WinFormsWCFTester) which uses
net.tcp://localhost:2202/Service1
and has the following code on a WinForm
namespace MyWCFService
{
public partial class Form1 : Form
{
IService1 IService1 = null;
public Form1() { InitializeComponent(); }
private void Form1_Load(object sender, EventArgs e)
{
EndpointAddress address = new EndpointAddress(new Uri("net.tcp://localhost:2202/Service1"));
NetTcpBinding binding = new NetTcpBinding();
ChannelFactory<IService1> factory = new ChannelFactory<IService1>(binding, address);
IService1 = factory.CreateChannel();
}
private void btnTest_Click(object sender, EventArgs e)
{
lblResponse.Text = IService1.GetData(txtSomeText.Text);
}
}
}
I also have a Delphi 7 test client (Delphi7WCFTester) which uses address
http://localhost:8732/Design_Time_Addresses/MyWCFService/Service1/
Note: the address comes from the WSDL generated by Add Service Reference when my WinFormsServiceHost is running. I use the updated WSDL Importer to create a Pascal proxy class for Delphi 7.
The situation on my PC (even stranger things happen when I move the code to another PC or worse - eg. a VM!)
When service is running (hosted by WCF Service Host - WcfSvcHost.exe invoked by VS2010), Webbrowser can navigate to
http://localhost:8732/Design_Time_Addresses/MyWCFService/Service1/
and telnet can connect to Localhost 8732. My Delphi client (Delphi7WCFTester) can connect and works properly, but my WCF client (WinFormsWCFTester) cannot connect (Exception message "Could not connect to net.tcp://localhost:2202/Service1 ... TCP error code 10061 ... target machine actively refused it 127.0.0.1:2202")
When service is being hosted by my WinFormsServiceHost and running in the Visual Studio debugger, Webbrowser can navigate to http://localhost:8732/Design_Time_Addresses/MyWCFService/Service1/ and telnet can connect to both ports 8732 or 2202. Both clients (WinFormsWCFTester and Delphi7WCFTester) can connect and work properly.
When service is being hosted by WinFormsServiceHost and running independently as exe (I use Ctrl-F5 from VS2010), neither address can be browsed with Webbrowser. Telnet can connect to 2202 but not 8732. My WinFormsWCFTester client connects and works properly, but my Delphi7WCFTester can't connect.
My Question
As you can probably tell from my exhaustive description of my situation, I'm a little lost. I need some guidance to get back in control of what's happening. Both clients should connect and work properly regardless how the service is being hosted. I know I have a lot to learn. I hope somebody can lead me in the right direction with a few important pointers.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
似乎您期望单个客户端应用程序(Delphi 或 WinForm)连接到不同的服务实例而不更改客户端配置。您已为 netTcpBinding 配置了 WinForm 服务实例,并为 basicHttpBinding 配置了 MyWCFService 实例。 Delphi 客户端只能连接到 MyWCFService 实例,因为它们都使用 basicHttpBinding,而 WinForm 客户端只能连接到 WinForm 实例,因为它们都使用 netTcpBinding。
为了实现您认为应该起作用的功能,您需要配置两个服务实例以公开 basicHttpBinding 和 netTcpBinding 的端点。我从未尝试过在 WinForm 应用程序中使用 basicHttpBinding,但我认为这应该可行。
Seems like your are expecting a single client app (Delphi or WinForm) to connect to the different service instances without changing the client configuration. You have the WinForm service instance configured for netTcpBinding and the MyWCFService instance configured for basicHttpBinding. The Delphi client can only connect to the MyWCFService instance because they're both using basicHttpBinding and the WinForm client can only connect to WinForm instance because they both use netTcpBinding.
To achieve what you think should work, you need to configure both service instances to expose endpoints for both basicHttpBinding and netTcpBinding. I've never tried to use basicHttpBinding within a WinForm app but I think that should work.