none
WCF Client issue when using net.tcp binding RRS feed

  • Question

  • Hello,

    I am very new to WCF and trying to understand it. I have created a very simple wcf host/client to test the water. WCF client and host use net.tcp binding programmatically (I did not use config file to make sure my parameters are use). From the host, I created the host with servicehost then addserviceendpoint with the address being "net.tcp://machine.domainname:9000". From the client, I used channelfactory and createchannel to create proxy for accessing the library using the exact same binding hardcoded in the program.

    Compiled and running were successful when both the host and client are on the same machine. But when the client is on a different machine in the network (I can ping to the machine), and the client was run, nothing happened and no error as far as I could tell. How do I find out what was wrong on the remote client? Does anyone more experienced than me know what tool to use to find out what went wrong?

    Thanks!

    Friday, March 22, 2013 4:11 PM

Answers

  • Hi,

    I tested on my side based on the contract and service class you provided, I can call the service from another machine(on the same domain). After adding a service reference( create proxy class), add the code below(client on another machine):

     public Form1()
            {
    
                InitializeComponent();
                NetTcpBinding myBinding = new NetTcpBinding();
                myBinding.Security.Mode = SecurityMode.None;
                // Create the address string, or get it from configuration.
                string tcpUri = "net.tcp://ipaddress:9000/Servicetest";
    
                // Create an endpoint address with the address.
                EndpointAddress myEndpointAddress = new EndpointAddress(tcpUri);
                ServiceReference1.Service1Client client = new ServiceReference1.Service1Client(myBinding, myEndpointAddress);
                textBox1.Text = client.AddInt(12, 45).ToString();
            }

    Below is the test code for the service(host the service).

     static void Main(string[] args)
            {
                ServiceHost host = new ServiceHost(typeof(WcfServiceLibrary3.Service1),new Uri("net.tcp://ipaddress:9000/Servicetest"));
                host.AddServiceEndpoint(typeof(WcfServiceLibrary3.IService1), new NetTcpBinding(SecurityMode.None,false),"");
                ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
    
                // If not, add one
                if (smb == null)
                    smb = new ServiceMetadataBehavior();
    
                //smb.HttpGetEnabled = true;
    
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
    
                host.Description.Behaviors.Add(smb);
    
    
                host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
                  MetadataExchangeBindings.CreateMexTcpBinding(),
                  "mex");
                
                host.Opened += delegate
                {
                    Console.WriteLine("service started!");
                };
                host.Open();
                Console.ReadLine();
                host.Close();
            }

    Note: When call the service and keep the service running on its machine. Below thread which also include samples.

    #Possible to use Self-Host for remote calls?

    http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/c6e332bf-c7ff-4032-b6c9-20b593249343

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by FrankTo Wednesday, March 27, 2013 5:15 PM
    • Edited by Haixia_XieModerator Thursday, July 11, 2013 1:44 AM spell error
    Wednesday, March 27, 2013 7:42 AM
    Moderator
  • Hi,

    If you want to set the configurations in the App.config file( also add the mexTcpBinding in it), it would similar to:

    <system.serviceModel>
        <services>
          <service name="WcfServiceLibrary1.Service1" behaviorConfiguration="WcfServiceLibrary1.Service1Behavior">
            <host>
              <baseAddresses>
            
                <add baseAddress="net.tcp://ipaddress:9000/Servicetest"   />          
              </baseAddresses>
            </host>
    
                   <!-- endpoint : TCP -->
            <endpoint address="nettcpHelloWorldService"
                      binding="netTcpBinding" bindingConfiguration="" name="tcpEndpoint"
                      contract="WcfServiceLibrary1.IService1" />
    
            <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="WcfServiceLibrary1.Service1Behavior">
              <serviceMetadata/>
              <serviceDebug includeExceptionDetailInFaults="False" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by FrankTo Monday, April 1, 2013 11:53 AM
    Thursday, March 28, 2013 2:30 AM
    Moderator
  • Hi,

    Please make sure the files(e.g IYourService1 and YourService1) which used to define the service are located at 'WCFLib.Calculator' project, and you have referenced the 'WCFLib.Calculator' project for your application that used to host your service( it would be a Console app in above sample).

    And you need specify a relative address for the endpoint instead of a absolute one, since you have specified a baseAddress which is absolute.

    <endpoint
              address="net.tcp://xxx.xxx.xxx.xxx/CalculatorTest"
    ______should be a relative address

    In addition, the app.config should located at the project that host the service. Like below:

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by FrankTo Monday, April 1, 2013 11:52 AM
    Friday, March 29, 2013 3:22 AM
    Moderator

All replies

  • Hi,

    You can take a look at a discussion in this post to get how to access a self-hosting wcf service from a different machine.

    >>and the client was run, nothing happened and no error as far as I could tell.

    Do you try set a breakpoint to check?

    There may be some issue related to network settings, such as firewall( the request may have been blocked by the firewall), DNS and proxy server.

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, March 25, 2013 7:16 AM
    Moderator
  • Hi,

    Thanks for the reply. You mentioned that firewall may have blocked the communication. I was told that the remote and the host computers are in the same subnet with no firewall blocking the communication because the computers are internal of our organization and do not have public facing settings. However, how do we find out for sure that the firewall has actually not interfered?

    Monday, March 25, 2013 6:17 PM
  • Hi,

    As per my knowledge, every machine has its firewall, you can try turn off the firewall to test.

    #Turn Windows Firewall on or off

    http://windows.microsoft.com/en-us/windows-vista/turn-windows-firewall-on-or-off

    If the issue still exists, you may try use fiddler or enable tracing for your service to help to diagnose the issue. And please give more information on how do you try to call the service.

    #How to enable WCF traces programmatically?

    http://wcfpro.wordpress.com/2010/11/21/how-to-add-wcf-traces-programmatically/

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, March 26, 2013 7:50 AM
    Moderator
  • Thanks again, Haixia.

    I followed your instruction and it looks like you were right, I turned off the firewall and was able to move a bit further. However, I encountered another error (please note, if the client and host were on the same machine, this issue were not happening)

    ---------------------------------------------

    See the end of this message for details on invoking
    just-in-time (JIT) debugging instead of this dialog box.

    ************** Exception Text **************
    System.ServiceModel.CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.

    Server stack trace:
       at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrNotOpen()
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

    Exception rethrown at [0]:
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at WCFLib.ICalculator.Add(Int32 arg1, Int32 arg2)
       at WCFClient.CalculatorClient.bResult_Click(Object sender, EventArgs e) in c:\xxxxxxx\WCFClient\CalculatorClient.cs:line 37
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

    ************** Loaded Assemblies **************
    mscorlib
        Assembly Version: 4.0.0.0
        Win32 Version: 4.0.30319.18033 built by: FX45RTMGDR
        CodeBase: file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll
    ----------------------------------------
    WCFClient
        Assembly Version: 1.0.0.0
        Win32 Version: 1.0.0.0
        CodeBase: file:///C:/xxx/WCFClient/bin/Debug/WCFClient.exe
    ----------------------------------------
    System.Windows.Forms
        Assembly Version: 4.0.0.0
        Win32 Version: 4.0.30319.18037 built by: FX45RTMGDR
        CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
    ----------------------------------------
    System.Drawing
        Assembly Version: 4.0.0.0

    This is what I did:

    I have a host calling a dll, the host is running while a client was trying to connect.
    For the library dll, I have an interface

        public interface ICalculator
        {
            [OperationContract(Name="AddInt")]
            int Add(int arg1, int arg2);
            [OperationContract(Name = "AddDouble")]
            Double Add(Double arg1, Double arg2);
        }

    then an implementation class derived from it
        public class Calculator : ICalculator
        {
            public int Add(int arg1, int arg2)
            {
                return arg1+arg2;
            }
            public Double Add(Double arg1, Double arg2)
            {
                return arg1 + arg2;
            }

    The host is a simple console application:

        class Program
        {
            static void Main(string[] args)
            {
                ServiceHost host = new ServiceHost(typeof(Calculator));
                host.AddServiceEndpoint(typeof(ICalculator), new NetTcpBinding(), "net.tcp://xxx.xxx.xxx.xxx:9000");
                host.Open();
                Console.ReadLine();
                host.Close();
            }
        }

    The client is a window form, I initiate the instance when the form started by creating a factory channel:
                ChannelFactory<ICalculator> ch;
                ch = new ChannelFactory<ICalculator>(new NetTcpBinding(), "net.tcp://xxx.xxx.xxx.xxx:9000");
                proxy = ch.CreateChannel();

    and when the appropriate button is clicked, the event will trigger the call to the proxy:
            private void bResult_Click(object sender, EventArgs e)
             {
                 tboxResult.Text=proxy.Add(12, 45).ToString();
             }

    Do you see any issue with this? Again, it worked when the client and host were on the same machine... I must have missed something that I do not know I missed...

     

     


    • Edited by FrankTo Tuesday, March 26, 2013 12:21 PM
    Tuesday, March 26, 2013 12:20 PM
  • Hi,

    I tested on my side based on the contract and service class you provided, I can call the service from another machine(on the same domain). After adding a service reference( create proxy class), add the code below(client on another machine):

     public Form1()
            {
    
                InitializeComponent();
                NetTcpBinding myBinding = new NetTcpBinding();
                myBinding.Security.Mode = SecurityMode.None;
                // Create the address string, or get it from configuration.
                string tcpUri = "net.tcp://ipaddress:9000/Servicetest";
    
                // Create an endpoint address with the address.
                EndpointAddress myEndpointAddress = new EndpointAddress(tcpUri);
                ServiceReference1.Service1Client client = new ServiceReference1.Service1Client(myBinding, myEndpointAddress);
                textBox1.Text = client.AddInt(12, 45).ToString();
            }

    Below is the test code for the service(host the service).

     static void Main(string[] args)
            {
                ServiceHost host = new ServiceHost(typeof(WcfServiceLibrary3.Service1),new Uri("net.tcp://ipaddress:9000/Servicetest"));
                host.AddServiceEndpoint(typeof(WcfServiceLibrary3.IService1), new NetTcpBinding(SecurityMode.None,false),"");
                ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
    
                // If not, add one
                if (smb == null)
                    smb = new ServiceMetadataBehavior();
    
                //smb.HttpGetEnabled = true;
    
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
    
                host.Description.Behaviors.Add(smb);
    
    
                host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
                  MetadataExchangeBindings.CreateMexTcpBinding(),
                  "mex");
                
                host.Opened += delegate
                {
                    Console.WriteLine("service started!");
                };
                host.Open();
                Console.ReadLine();
                host.Close();
            }

    Note: When call the service and keep the service running on its machine. Below thread which also include samples.

    #Possible to use Self-Host for remote calls?

    http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/c6e332bf-c7ff-4032-b6c9-20b593249343

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by FrankTo Wednesday, March 27, 2013 5:15 PM
    • Edited by Haixia_XieModerator Thursday, July 11, 2013 1:44 AM spell error
    Wednesday, March 27, 2013 7:42 AM
    Moderator
  • Thank you so much for taking time to look into it! I did not know that much was involved when the client is on different machine. I will try it out on mine and will let you know if it work on mine... again, thank you, HaiXia... very much appreciated!
    Wednesday, March 27, 2013 12:41 PM
  • Thank you, HaiXia... it is amazing... your instruction works!!!! Thanks a bunch!
    Wednesday, March 27, 2013 5:14 PM
  • Hi HaiXia,

    A follow up question if that is okay with you. What should I do to make my host and client reads the app.config instead of hardcoding the endpoints? I guess I make this a follow up question because I want to keep the context of my question instead of restarting it from fresh.

    The following is the content of my config file:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <services>
          <service name="WCFLib.Calculator">
            <endpoint
              address="net.tcp://xxx.xxx.xxx.xxx:9000/servicetest"
              binding="netTcpBinding"
              contract="WCFLib.ICalculator" />
            <host>
              <baseAddresses>
                <add baseAddress="net.tcp://xxx.xxx.xxx.xxx:9000/"/>
              </baseAddresses>
            </host>
          </service>
        </services>
      </system.serviceModel>
    </configuration>

    In my host I used this code instead of your original one:

           static void Main(string[] args)
            {
                ServiceHost host = new ServiceHost(typeof(Calculator));
    // The rest remains the same ....
                ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
                if (smb == null) smb = new ServiceMetadataBehavior();
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                host.Description.Behaviors.Add(smb);
    
                host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
                host.Opened += delegate
                {
                    Console.WriteLine("service started!");
                };
                host.Open();
                Console.ReadLine();
                host.Close();
            }
    

    I moved the exe,dll,app.config to the host machine but I got this error:

    Is there something I missed in the config?

    Thanks again!

    Wednesday, March 27, 2013 8:04 PM
  • Hi,

    If you want to set the configurations in the App.config file( also add the mexTcpBinding in it), it would similar to:

    <system.serviceModel>
        <services>
          <service name="WcfServiceLibrary1.Service1" behaviorConfiguration="WcfServiceLibrary1.Service1Behavior">
            <host>
              <baseAddresses>
            
                <add baseAddress="net.tcp://ipaddress:9000/Servicetest"   />          
              </baseAddresses>
            </host>
    
                   <!-- endpoint : TCP -->
            <endpoint address="nettcpHelloWorldService"
                      binding="netTcpBinding" bindingConfiguration="" name="tcpEndpoint"
                      contract="WcfServiceLibrary1.IService1" />
    
            <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="WcfServiceLibrary1.Service1Behavior">
              <serviceMetadata/>
              <serviceDebug includeExceptionDetailInFaults="False" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by FrankTo Monday, April 1, 2013 11:53 AM
    Thursday, March 28, 2013 2:30 AM
    Moderator
  • HaiXia,

    I think I am almost there but something I may still be missing that held me up. I have followed your suggestion on app.config then made some changes on the code of the host, but I kept getting this error:

    "Could not find a base address that matches scheme net.tcp for the endpoint with binding MetadataExchangeTcpBinding. Registered base address schemes are []."

    This is the app.config

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <services>
          <service name="WCFLib.Calculator" behaviorConfiguration="WCFLib.CalculatorBehavior">
            <host>
              <baseAddresses>
                <add baseAddress="net.tcp://xxx.xxx.xxx.xxx:9000/"/>
              </baseAddresses>
            </host>
            <endpoint
              address="net.tcp://xxx.xxx.xxx.xxx/CalculatorTest"
              binding="netTcpBinding" bindingConfiguration="" name="tcpEndPoint"
              contract="WCFLib.ICalculator" />
            <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="WCFLib.CalculatorBehavior">
              <serviceMetadata/>
              <serviceDebug includeExceptionDetailInFaults="False"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>

    And this is the code for my host:

    namespace WCFHost
    {
        class Program
        {
            static void Main(string[] args)
            {
                ServiceHost host = new ServiceHost(typeof(Calculator));
    
                ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
                if (smb == null)
                {
                    smb = new ServiceMetadataBehavior();
                }
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                host.Description.Behaviors.Add(smb);
                host.AddServiceEndpoint( ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
                host.Opened += delegate
                {
                    Console.WriteLine("service started!");
                };
                host.Open();
                Console.ReadLine();
                host.Close();
            }
        }
    }

    If I cut everything off like this:

        class Program
        {
            static void Main(string[] args)
            {
                ServiceHost host = new ServiceHost(typeof(Calculator));
                host.Opened += delegate
                {
                    Console.WriteLine("service started!");
                };
                host.Open();
                Console.ReadLine();
                host.Close();
            }
        }
    

    I will get this error:

    "Service 'WCFLib.Calculator' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element."

    Anything else that I may need to tweak?

    Thanks!


    • Edited by FrankTo Thursday, March 28, 2013 6:30 PM
    Thursday, March 28, 2013 6:18 PM
  • Hi,

    Please make sure the files(e.g IYourService1 and YourService1) which used to define the service are located at 'WCFLib.Calculator' project, and you have referenced the 'WCFLib.Calculator' project for your application that used to host your service( it would be a Console app in above sample).

    And you need specify a relative address for the endpoint instead of a absolute one, since you have specified a baseAddress which is absolute.

    <endpoint
              address="net.tcp://xxx.xxx.xxx.xxx/CalculatorTest"
    ______should be a relative address

    In addition, the app.config should located at the project that host the service. Like below:

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by FrankTo Monday, April 1, 2013 11:52 AM
    Friday, March 29, 2013 3:22 AM
    Moderator
  • Thanks again, HaiXia. Thanks to your illustration, I realized that my app.config on the host was in the incorrect location. Moved it to the proper directory and it worked.

    One last question... how should the app.config in the host be related to the app.config in the client since the client is using proxy and not the real WCFLib? I got the warning when I placed the app.config I used on the host to the client.

    Please find attached the name of my service reference and the app.config.

    From the client, should I just call the proxy with no parameters as below? If so, how does wcfclient know which endpoint I want to use if app.config allows multiple endpoints?

    proxy = new CalculatorInstance.CalculatorClient();

    From the client:

    app config file in the client, got warning the WCFLib.ICalculator does not exist. It doesn't since we used proxy. How do we refer the proxy?

    <services> <service name="WCFLib.Calculator" behaviorConfiguration="WCFLib.CalculatorBehavior"> <host> <baseAddresses> <add baseAddress="net.tcp://xxx.xxx.xxx.xxx:9000/"/> </baseAddresses> </host> <endpoint address="CalculatorTest" binding="netTcpBinding" bindingConfiguration="" name="tcpEndPoint" contract="WCFLib.ICalculator" /> <---I got error/warning here <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="WCFLib.CalculatorBehavior"> <serviceMetadata/> <serviceDebug includeExceptionDetailInFaults="False"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>

    Thank you!


    • Edited by FrankTo Friday, March 29, 2013 12:54 PM
    Friday, March 29, 2013 12:53 PM
  • Hi,

    The app.config in the host is for the service but not the client, the client has its own app.config.

    >>If so, how does wcfclient know which endpoint I want to use if app.config allows multiple endpoints?

    If you have multiple endpoints in the app.config, you need specify one when you use it.

    Refer#Multiple Endpoints

    http://msdn.microsoft.com/en-us/library/ms751515.aspx

    >>How do we refer the proxy?

    The proxy class has been generated when you add a service reference, you can use it to create a proxy instance.

    In addition, since your original issue on call service from a remote machine using nettcpbinding has been resolved, it would be best if you open up a new thread for the new questions. This will make answer searching in the forum easier and be beneficial to other community members as well.

    Thanks for your understanding and support.

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, April 1, 2013 9:49 AM
    Moderator