在 Web 应用程序中设置 WCF TCP 服务 [英] Setting up WCF TCP service in a web application

查看:18
本文介绍了在 Web 应用程序中设置 WCF TCP 服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经与这个问题斗争了好几天,从字面上看,一百篇文章提供了有关如何在 Web 应用程序中设置基于 WCF TCP 的服务的部分指南.如果有人可以帮助我,我会将这个问题变成一个完整的指南.

现状

net.tcp 连接在我的开发机器上工作.部署到 Windows Server 2008 R2 后,它也可在本地运行.但是,它不能远程工作,即使可以远程 telnet 到服务器上的端口 808.滚动到问题底部了解详情.如果可以,请帮忙.

我将为此详细信息创建一个新问题,并在得到结果后更新此问题的答案.

代码

我使用以下内容创建了 ServerHubService.svc:

命名空间 Manage.SignalR{[服务合约]公共类 ServerHubService{【经营合同】公共无效更新服务器状态(字符串服务器状态){//做一点事}}}

托管服务的应用程序的配置

按照在线教程,我将以下内容添加到我的 Web.config(我尝试了许多不同的变体).这是托管服务的 Web 应用程序的 Web.config,我稍后希望通过 TCP 连接到该服务.

<预><代码><配置><system.serviceModel><服务><service behaviorConfiguration="ServerHubBehavior"name="Manage.SignalR.ServerHubService"><端点地址=""绑定=netTcpBinding"bindingConfiguration="portSharingBinding"名称="MyServiceEndpoint"合同="Manage.SignalR.ServerHubService"><身份><dns value="localhost"/></身份></端点><端点地址="mex"绑定=mexTcpBinding"绑定配置=""名称="MyServiceMexTcpBidingEndpoint"合同=IMetadataExchange"/><主机><基地址><add baseAddress="net.tcp://test.mydomain.com:808/SignalR/ServerHubService.svc"/></baseAddresses></host></服务></服务><行为><服务行为><行为名称="ServerHubBehavior"><serviceMetadata httpGetEnabled="true"/><serviceDebug includeExceptionDetailInFaults="false"/></行为></serviceBehaviors></行为><绑定><netTcpBinding><binding name="portSharingBinding" portSharingEnabled="true"/></netTcpBinding></绑定><serviceHostingEnvironment aspNetCompatibilityEnabled="true"minFreeMemoryPercentageToActivateService="0" multipleSiteBindingsEnabled="true"/></system.serviceModel></配置>

httpGetEnabled="true" 很重要,否则您将无法创建对服务的服务引用.

配置运行 Web 应用程序的服务器

我正在我的具有 IIS 7.5 的开发机器上进行设置

我了解到 IIS Express(内置在 Visual Studio 中)不支持 net.tcp,所以我在 IIS 7.5 中使用 .NET 4.5 建立了一个新网站,该网站具有 net.tcp 绑定

我还转到网站的高级设置并将启用的协议设置为 http,net.tcp

我确保启用(并重新启动)Windows 功能非HTTP 激活.这是一项 Windows 功能,因此请查找打开或关闭 Windows 功能"来找到它.

确认网络应用程序正在运行

该网站适用于 Web 应用程序的其余部分.我将 test.mydomain.com 设置为指向 hosts 文件中的 127.0.0.1.我什至可以访问

I've been battling with this for days, literally going through a hundred articles giving partial guidelines on how to set up a WCF TCP based service in a web application. If someone can help me, I will make this question into a complete guideline.

Current status

The net.tcp connection works on my development machine. It also works locally after being deployed to a Windows Server 2008 R2. However, it doesn't work remotely, even though it's possible to telnet to port 808 on the server remotely. Scroll to the bottom of the question for details. Please help if you can.

I will create a new question for this detail and update this question with the answer if I get a result out of it.

Code

I created ServerHubService.svc with the following content:

namespace Manage.SignalR
{
    [ServiceContract]
    public class ServerHubService
    {
        [OperationContract]
        public void UpdateServerStatus(string serverStatus)
        {
            // Do something
        }
    }
}

Configuration of the application hosting the service

Following an online tutorial, I added the following to my Web.config (I tried MANY different variations). This is the Web.config of the web application hosting the service that I later want to connect to with TCP.

<configuration>
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="ServerHubBehavior"
      name="Manage.SignalR.ServerHubService">
        <endpoint address=""
              binding="netTcpBinding"
              bindingConfiguration="portSharingBinding"
              name="MyServiceEndpoint"
              contract="Manage.SignalR.ServerHubService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>

        <endpoint address="mex"
              binding="mexTcpBinding"
              bindingConfiguration=""
              name="MyServiceMexTcpBidingEndpoint"
              contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://test.mydomain.com:808/SignalR/ServerHubService.svc" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServerHubBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netTcpBinding>
        <binding name="portSharingBinding" portSharingEnabled="true"/>
      </netTcpBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
      minFreeMemoryPercentageToActivateService="0" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
</configuration>

httpGetEnabled="true" is important because otherwise you cannot create a service reference to the service.

Configuration of the server where the web application is running

I am setting this up on my development machine which has IIS 7.5

I read that IIS Express (built into Visual Studio) doesn't support net.tcp, so I set up a new website in IIS 7.5 using .NET 4.5 and that has a net.tcp binding

I also went to Advanced Settings for the website and set Enabled Protocols to http,net.tcp

I ensured that the Windows Feature Non-HTTP Activation is enabled (and restarted). It's a Windows Feature so look for "Turn Windows features on or off" to find this.

Confirming the web application is running

The website works fine for the rest of the web application. I set up test.mydomain.com to point to 127.0.0.1 in my hosts file. I can even visit http://test.mydomain.com/SignalR/ServerHubService.svc and it will show me a nice auto generated page from .NET, explaining how to use this service.

So far so good.

The page generated by .NET tells me to use this address to generate a connection to my service:

net.tcp://computername/SignalR/ServerHubService.svc/mex

Trying to connect to the service as a client

If you do not remember to set httpGetEnabled="true" you will get an error when trying to create a service reference to it. If you use the WCF Test Client (also a tool included in Visual Studio) and didn't set httpGetEnabled, you will get an error like the following:

Error: Cannot obtain Metadata from net.tcp://computername/SignalR/ServerHubService.svc/mex

If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata

Exchange Error URI: net.tcp://computername/SignalR/ServerHubService.svc/mex Metadata contains a reference that cannot be resolved: 'net.tcp://computername/SignalR/ServerHubService.svc/mex'. Could not connect to net.tcp://computername/SignalR/ServerHubService.svc/mex. The connection attempt lasted for a time span of 00:00:04.0032289.

TCP error code 10061: No connection could be made because the target machine actively refused it [2001:0:4137:9e76:c81:a4c:a547:b2fd]:808. No connection could be made because the target machine actively refused it [2001:0:4137:9e76:c81:a4c:a547:b2fd]:808

However, if you've done everything as above, you should be able to add a reference to the service.

Calling methods in the service

When trying to call a simple Hello World method in the service from the WCF Test Client, it returns the following error:

Could not connect to net.tcp://computername/SignalR/ServerHubService.svc. The connection attempt lasted for a time span of 00:00:04.0002288. TCP error code 10061: No connection could be made because the target machine actively refused it.

This is inner stacktrace that is included in with the error:

No connection could be made because the target machine actively refused it [2001:0:5ef5:79fb:3884:a:a547:b2fd]:808 at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress) at System.Net.Sockets.Socket.Connect(EndPoint remoteEP) at System.ServiceModel.Channels.SocketConnectionInitiator.Connect(Uri uri, TimeSpan timeout)

If you use netstat -an |find /i "listening" to see that nothing is listening on port 808, it's probably because the Net.Tcp Listener Adapter service is not running.

Confirmation

The call goes through now, but some confirmation is needed before it can be declared a success. I need to confirm that this is in fact net.tcp call on port 808 and not actually a call on the http endpoint. I am trying to do this with Wireshark, but it doesn't show up, probably because it's a call happening from and to my local machine.

Deployment

The last challenge to conquer would be to deploy this on a web server, ensuring that what works on the development machine, also works on the web server.

It doesn't work after publish to a Windows Server 2008 R2. It gives the common SocketException: An existing connection was forcibly closed by the remote host.

It works well locally on the server, but it doesn't work remotely.

Here is the checklist used to check the server:

  • Is the Net.Tcp Listener Adapter service running? Yes
  • Is the IIS site binding to net.tcp set to 808:*? Yes
  • Is Enabled Protocols under Advanced Settings for the site in IIS set to http,net.tcp? Yes
  • Is the server listening on port 808? Yes, checked with netstat -an |find /i "listening"
  • Is a port 808 open in the firewall? Yes.
    • Firewall is turned off on the server.
    • I can telnet to the server on port 808 from outside with telnet mydomain.com 808
  • In the configuration of the service on the server, the following was confirmed:
    • baseAddress is adjusted to net.tcp://mydomain.com:808/SignalR/ServerHubService.svc
    • This was localhost before, but changed to mydomain.com after it didn't work on the server: <identity><dns value="mydomain.com" /></identity>
  • It has been tested with a client locally on the server and on another server. Both can connect to port 808 with telnet and both give the same error message.

What configuration could be missing on the server? I am so close to the goal. Please assist me in troubleshooting this and complete the question.

Here is the client configuration on the server calling the service:

<system.serviceModel>
  <bindings>
    <netTcpBinding>
      <binding name="MyServiceEndpoint" />
    </netTcpBinding>
  </bindings>
  <client>
    <endpoint address="net.tcp://mydomain.com:808/SignalR/ServerHubService.svc"
      binding="netTcpBinding" bindingConfiguration="MyServiceEndpoint"
      contract="ServerHubService.ServerHubService" name="MyServiceEndpoint">
      <identity>
        <dns value="mydomain.com" />
      </identity>
    </endpoint>
  </client>
</system.serviceModel>

I also tried without 808 configured in the endpoint, as this is rumored to be the default port for net.tcp connections. However, it still gives the same result.

Instead of trying lots of things randomly, the good question is perhaps: How does one debug something like this? Can I install a program on either server that will tell me exactly WHY this call is being blocked?

With Wireshark configured like this, it's possible to look at the call coming to the server on port 808 and possibly determine why the call doesn't work. However, I have no idea how to analyze this at present time.

Good luck

I gave up and implemented this in the socket layer instead. It worked immediately. I hope this can help someone else, though. I'm setting an answer because many of the issues were solved and it did work locally eventually, so any problem remaining is probably related to me specific environment.

解决方案

You have to generate the Proxy based on the metadata exposed over HTTP for tcp.(make sure httpGetEnabled is set to true). The address you use at the client should be the hosted address. Please refer the below post.

http://blogs.msdn.com/b/swiss_dpe_team/archive/2008/02/08/iis-7-support-for-non-http-protocols.aspx

这篇关于在 Web 应用程序中设置 WCF TCP 服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆