简体   繁体   中英

WCF: Self-host a NetTcp service, doesn't resolve

I am trying to host a WCF service, using NetTcpBinding in a Windows service. (I'm going to use it as an API for various clients both Web and Windows32) Obviously, I am doing this within a test host before putting it in a Windows service.

I have the following contract:

namespace yyy.xxx.Server.API.WCF
{
    [ServiceContract]
    public interface ISecureSessionBroker
    {
        [OperationContract]
        string GetSessionToken(string username, string encryptedPassword, string clientApiKey, string clientAddress);
    }
}

with the following implementation:

namespace yyy.xxx.Server.API.WCF
{
    public class SecureSessionBroker : ISecureSessionBroker
    {
        #region ~ from ISecureSessionBroker ~

        public string GetSessionToken(string username, string encryptedPassword, string clientApiKey, string clientAddress)
        {
            return Guid.NewGuid().ToString();
        }

        #endregion
    }
}

I am hosting the WCF service using the code below (within a class/method):

try
{
    _secureSessionBrokerHost = new ServiceHost(typeof(SecureSessionBroker));
    NetTcpBinding netTcpBinding = new NetTcpBinding();
    _secureSessionBrokerHost.AddServiceEndpoint(typeof(ISecureSessionBroker), netTcpBinding, "net.tcp://localhost:8080/secureSessionBrokerTcp");
    int newLimit = _secureSessionBrokerHost.IncrementManualFlowControlLimit(100);
    // Open the ServiceHost to start listening for messages.
    _secureSessionBrokerHost.Open();

}
catch (Exception ex)
{
throw;
}

The key thing here is that I do not want to have to rely on an App.config file. Everything must be configured programmatically. When I run this code, the service appears to come "up" and listen. (ie. I have no exceptions)

BUT when I use the client code below:

string secureSessionBrokerUrl = string.Format("{0}/secureSessionBrokerTcp","net.tcp://localhost/8080",url);
EndpointAddress endpointAddress=new EndpointAddress(secureSessionBrokerUrl);
System.ServiceModel.Channels.Binding binding = new NetTcpBinding();
yyy.xxx.Windows.AdminTool.API.WCF.SecureSessions.SecureSessionBrokerClient
    client = new yyy.xxx.Windows.AdminTool.API.WCF.SecureSessions.SecureSessionBrokerClient(binding,endpointAddress);
string sessionToken=client.GetSessionToken("", "", ""); // exception here
MessageBox.Show(sessionToken);

... I always get an exception. At the moment, I am getting:

This request operation sent to net.tcp://localhost:8080/secureSessionBrokerTcp did not receive a reply within the configured timeout (00:01:00). The time allotted to this operation may have been a portion of a longer timeout. This may be because the service is still processing the operation or because the service was unable to send a reply message. Please consider increasing the operation timeout (by casting the channel/proxy to IContextChannel and setting the OperationTimeout property) and ensure that the service is able to connect to the client.

So I guess it cannot resolve the service.

Where am I going wrong? How do I test for the existence of the service over TCP? I have used the SvcTraceViewer and I just get the same message, so no news there.

I would prefer to ask the user for a URL of the service, so they would enter "net.tcp://localhost:8080" or something, which would then be used as a BaseAddress for the various calls to the SecureSessionBroker (and other) WCF services ... without resorting to App.config.

Unfortunately, all the examples I can find all use the App.config.

Interestingly, I can host the service using the VS Host and the client connects fine. (Using: D:\\dev2008\\xxx\\yyy.xxx.Server>WcfSvcHost.exe /service:bin/debug/yyy. xxx.Server.dll /config:App.config)

Ok, it came to me in a flash of inspiration.

I was using a Windows Form (alarm bells) to "host" the service. Clicking out of the form, I used a bit of code to call the service (included) on a button click. Of course, the service was not in its own thread, so the service could not respond.

I've fixed it by putting the Service container (which contains the host) within its own thread:

Thread thread = new Thread(new ThreadStart(_serviceWrapper.Start));
thread.Start();

The Start() method sets up the ServiceHost.

I incorrectly thought that while a WCF Service Host will create threads for incoming requests, it will only do this if it is in its own non-blocking thread (ie. not a UI thread).

Hope it helps someone else.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM