Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a WCF Dual Service over the internet?

I followed this tutorial (at least based my WCF in this, coz I need then to work alike): http://www.eggheadcafe.com/tutorials/wcf/b5ada8df-58c5-492f-b368-457b3a4f137c/notify-client-applications-using-wcf-callbacks.aspx

It's working very well on my computer, but i need to use it over the internet. While trying to do this I heard (over the internet) that is better to use netTcpBiding.

I gonna have a server that is going to be aware of the number of clients online. I wanted a WFC service on my IIS in the server, and a windows service consuming it and notifying it. I need the callback coz the server sometime have to be able to execute some commands on the client.

I would be very pleased if anyone could help me.

Thanks in advance,

Edit:

Making myself clear: I just could not make it work over the internet. Can you guys show me how can i change my configurations (Web.config e App.config) to use netTcpBinding and work over the internet?

Thanks again,

Edit 2:

My Web.config in my WCFServiceApplication is:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <bindings>
      <wsDualHttpBinding>
        <binding name="WSDualHttpBinding_IPCWatcherWCFService" closeTimeout="00:01:00"
            openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
            bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
            maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
            messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00" />
          <security mode="Message">
            <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" />
          </security>
        </binding>
      </wsDualHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="TiT.PCWatcher.Server.WCFService.Services.PCWatcherWCFServiceBehavior" name="TiT.PCWatcher.Server.WCFService.Services.PCWatcherWCFService">
        <endpoint address="" binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IPCWatcherWCFService" contract="TiT.PCWatcher.Server.WCFService.Interfaces.IPCWatcherWCFService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="TiT.PCWatcher.Server.WCFService.Services.PCWatcherWCFServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

My App.config in my WindowsService is:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <wsDualHttpBinding>
        <binding name="WSDualHttpBinding_IPCWatcherWCFService" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
          maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
          textEncoding="utf-8" useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00" />
          <security mode="Message">
            <message clientCredentialType="Windows" negotiateServiceCredential="true"
              algorithmSuite="Default" />
          </security>
        </binding>
      </wsDualHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:25145/Services/PCWatcherWCFService.svc"
        binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IPCWatcherWCFService"
        contract="PCWatcherWCFServiceReference.IPCWatcherWCFService"
        name="WSDualHttpBinding_IPCWatcherWCFService">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

Just changing it to netTcpBinding does not work...

But i would be glad enough to jut be able to run this over the internet... I published the WCFService on IIS. Links:

https://www2.tcenter.com.br/monitor/PCWatcherWCFService.svc

OR

http://www2.tcenter.com.br:8080/monitor/PCWatcherWCFService.svc

Just changing the configs its enought to make it work through the internet? like i said, local it works just fine.

I thought that just changing the endpoint address on the client to one of the URL's above it whould work, but it did not...

The example that you linked hosts the service on the WPF. I don't know if it applys to my cenario...

i Think i'm gonna stick with the DualHttpBinding, you don't think that port forwarding it's good for my needs, i'm can have a lot of clients in one intranet and having the router decide wich one he is going to send info for it's no good right? or there's a way to make the router respond corretly to each and every machine conecting to my webserver through the same port?! (just asking, hehehe)

Thanks a lot in advance,

Edit on 21/06/2012:

Thanks for the reading. I was not able to get the service to work with netTcpBinding in LAN. I did a mock sample of my cenario. It's here. Called DualCommunicationTest.

When I started this post, i just wanted to know how to make this cenarion runing on internet. Just that. During my time searching for a solution before posting here, i readed that netTcpBinding is better. So i asked about it. It was just a side question.

So... my current needs on the post are:

How to use the sample i developed on the internet.

OR

How to make the sample i developed work with netTcpBinding AND then be able to use it on the internet. (I'm pretty sure Clunky Coder taught me the second part, on how to publish a net.tcp on the internet with the IIS and stuff, thanks a lot for that, but i was not able to test it yet, because i couldn't do a netTcp yet.)

I'm sorry if i'm not been clear enough, my English is not so good. sry and thanks again, a lot.

like image 801
Tanielian V. Barreira Avatar asked Jun 18 '12 12:06

Tanielian V. Barreira


1 Answers

netTcpBinding is better for duplex communication (communication with callbacks) and it's more performant than WSDualHttpBinding which is the preferred binding for duplex communication over HTTP. But you shouldn't really use netTcpBinding over the internet although you technically can and it might work, but the ports that netTcpBinding uses may be (and usually are) blocked by firewalls on the internet. When you send something across the internet, it makes lots of hops and goes through lots of routers and firewalls, and there is no guarantee that those routers and firewalls will have all ports open. But if you can open the ports (for netTcp it's TCP 808) on both the client and server endpoints (usually done by port forwarding on the router) it may work, but the general advice is not to use netTcpBinding over the internet. Having said that I have used it a couple of times for my services, and my clients have been able to consume the service over the internet without any problems-after I forwarded the ports on both the client and server ends.

In general for duplex communication over the internet you have the WSDualHttpBinding and if you have a Silverlight client (Silverlight doesn't support WSDualHttpBinding) you can use PollingDuplexHttpBinding.

I also recommend you read this.

EDIT:

To change that example to use netTcpBinding, just change the bindings in the config file to use netTcpBinding instead of wsDualHttpBinding. Have a look at this article, it does what the link you posted does, with netTcpBinding and more explanation.

EDIT 20/06/2012:

Making myself clear: I just could not make it work over the internet. Can you guys show me how can i change my configurations (Web.config e App.config) to use netTcpBinding and work over the internet?

Seems that you were able to get the service to work with netTcpBinding in LAN, so your earlier problem is now fixed and you're now having trouble hosting the service in IIS and publishing it online. When your service works in a LAN, it will work over the internet once you host it in IIS and forward the appropriate ports on the clients and servers routers, this is a common scenario and is documented well online. To do this You must host your service as an application in your IIS website. You need to make sure your service has a .svc file that points to the location of the service, then copy the contents of the App.Config (Service config file) to a new web.config (in the same physical directory as your App.config) and also remove the <host><baseAddresses> section in the newly created web.config, point the physical path of the application to the location of this service on your service host computer. Once that's taken care of, just be sure to edit the default website bindings to enable the specific bindings your service uses, for netTcpBinding go to: Website -> 'Edit Bindings...' -> 'Add...' then choose net.tcp and assign it the ports. Then on your application go to 'Advanced Settings' and enable net.tcp, netTcpBinding service will typically have http,net.tcp as it's enabled protocols. If you run into teething errors make sure the default app pool (or which ever application pool your website is using) has the required permissions to access and read the physical directory on the server in which the service resides.

Please read this and this, asking me to elaborate would just be repeating what they're saying.

EDIT 21/06/2012:

I just downloaded your service and hosted it in IIS and it's hosted fine, since its using HTTP and not nettcp then that means it works perfectly fine on the internet. If your service is something simple and you don't expect to do heavy processing with it (by the looks of it you're just trying to get the list of clients connected to it) then stick with wsDualHTTPBinding since the HTTP protocol will work in any environment and you don't have to worry about firewalls as you would with netTcpBinding. This is all I did to host the service in IIS (and make it available over the internet):

  1. Go to DefaultWebsite in IIS, right click, add application, under Alias just give your service any name you wish to be able to see in the URL. Select Default App Pool or ASP.NET 4.0 app pool.

  2. Point the physical path to where your .svc file is on your computer; for me its:

C:\Users\MyPC\Documents\DualCommunicationTest.Server\WcfServiceApp

  1. Under enabled protocols ensure that you have HTTP on port 80 or any other port, for example 8085, but you will need to forward this port on your router to the Service host computer. If your Service host is on IP 192.168.1.4 in your LAN, then on your router forward port 80 (or whatever port you use-say 8085) to computer 192.168.1.4.

And it's that easy.

like image 78
Mohammad Sepahvand Avatar answered Nov 27 '22 00:11

Mohammad Sepahvand