WCF Named Pipe Another Endpoint Error but no other endpoints? - c#

I'm using a DuplexChannelFactory to create a named pipe on net.pipe://localhost/test. However, when I run my program, I get an error: Cannot listen on pipe name "net.pipe://localhost/" because another pipe endpoint is already listening on that name.
So I tried to see whether this was actually the case, by opening a powershell and typing in [System.IO.Directory]::GetFiles("\\.\\pipe\\), but there is no mention of localhost.
I then also tried to change the address net.pipe://localhost/test to net.pipe://anything/test but it still didn't work.
Finally I restarted the computer and it worked. But restarting the computer is not optimal, and I restarted it again earlier today and it broke again.
Could there be any other reason why I would get this error?

WCF Named pipes operate on a different system to regular nameed pipes. When you open a regular named pipe on localhost, you will get a pipe at \.\pipe\localhost, but when you open a WCF pipe you will get \.\pipe\some-guid-xxxx-xxxx. This generated GUID is consistent for WCF named pipes of the same name, which is why it works seamlessly. (see Prevent Named Pipes Conflict)
Now, in my code, I wanted to create a named pipe on localhost. It didn't show up in [System.IO.Directory]::GetFiles("\\.\\pipe\\), because WCF uses a UUID.
The workaround I used in the end is to specify the pipe url as net.pipe\localhost\something_specific_to_me and have an additional AddServiceEndpoint(...,"something_else"), so that the final pipe could be connected to via net.pipe\localhost\something_specific_to_me\something_else.

Related

Connect to Azure Redis Cache via HTTP

I'm using "ServiceStack.Redis" to connect to Redis and it works correctly on my development machine.
Basically, I open the connection via this line:
client = new RedisClient(host);
Where host, on my development machine, is "localhost".
Now, I'd like to upload my application to Azure, so I created a cache in Azure and I'm trying to connect to it by passing the following connection string:
XXX.redis.cache.windows.net,ssl=false,password=YYY
The creation of the "RedisClient" seems to work but when I try to perform an operation (the first one to be executed being client.RemoveByPattern("...")), I get the following error:
Exception Details: System.Net.Sockets.SocketException: No such host is
known
Note that I allowed the cache to be connected to via HTTP, so normally, the port 6379 is unblocked and accessible.
All the example I found over Internet are using "ConnectionMultiplexer" but this class does not seem to be found in the NuGet package "ServiceStack.Redis".
What am I doing wrong?
I was having the same(similar?) issue connecting to Azure Redis with ServiceStack, in the end it was working out the correct syntax for the connection that worked for me. XXX.redis.cache.windows.net?ssl=true
Found some help here https://github.com/ServiceStack/ServiceStack.Redis, but to quote the connection strings section had examples;
"Redis Connection strings have been expanded to support the more versatile URI format which is now able to capture most of Redis Client settings in a single connection string (akin to DB Connection strings).
Redis Connection Strings supports multiple URI-like formats, from a simple hostname or IP Address and port pair to a fully-qualified URI with multiple options specified on the QueryString."
Some examples of supported formats:
localhost
127.0.0.1:6379
redis://localhost:6379
password#localhost:6379
clientid:password#localhost:6379
redis://clientid:password#localhost:6380?ssl=true&db=1
NOTE: I used the final example here but without the redis:// bit as I found this was not needed in Azure.

Creating a Named Pipe sometimes fails, randomly

The problem at hand is to have a "Container" app and a "Child" app communicate via a named pipe. The problem is the pipe sometimes fails to be created.
When things go smoothly, communication works pretty well.
The problem I'm seeing is that sometimes the Pipe server will fail to initialize. I can see why it happens in some instances, namely that the previous version of my app is still running in the background and did not exit properly for some reason so it's hanging on to the pipe. But, I have also seen it fail when I put in a new random name for the pipe that should not be used by any other processes, this is the part that worries me. Perhaps it is a limitation set by the OS on the same process name OR on visual studio debug mode?
To illustrate this, I have some code that tries to create a server steam (the pipe server):
NamedPipeServerStream server = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1);
The exception I often see is this:
Could not create server:System.IO.IOException: All pipe instances are busy.
I have tried a few variations of this with security options passed to the pipe + increasing the number of allowed servers from 1 to something higher but then the "Child"/Client might connect to what I assume is another process that is not properly closed out, and hence the wrong pipe server.
My ideas are:
figure out a way to "force" take over a pipe.
figure out a way to close out all dead instances of my own app somehow?
negotiate a new pipe to use writing some random pipe name to a file that both apps can read in first? This seems overkill and still not ideal if I'm having the odd behavior when I can't create a pipe even if the name is different.
Since this is hard to recreate, I am simulating the problem by doing:
var pipeName = "myApp22";
NamedPipeServerStream server = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1);
// Here I would want to catch the exception and then force close, then repeat this:
NamedPipeServerStream server = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1);
Any input would be appreciated. Thanks.

Connecting to Websphere MQ queue manager works in application A but not in application B

I have two console applications, A and B.
The application A was created for test purposes and works as expected.
The application B does not work although it is basically a copy-paste of A's code:
System.Console.Write("User Name: ");
string username = System.Console.ReadLine();
System.Console.Write("Password: ");
string password = ConsoleReadPassword();
System.Console.WriteLine();
//user and password required because I am also a privileged user
//(member of mqm group)
MQEnvironment.UserId = username;
MQEnvironment.Password = password;
//for application B this line throws exception with code 2538
var queueManager = new MQQueueManager("TEST.QUEUE.MANAGER", "CLIENT.CONN.CHANNEL", "localhost(1414)");
Error code 2538 means "Host not available" which is weird because application A has no problems connecting to the same host.
This is how the MQ Server looks in MQ Explorer:
Queue managers:
Queues:
Listeners:
Channels:
Two server channels
Channel auth records:
Default channel authentication record which prevents MQ admins from connecting to queue managers. It was slightly modified (added ~ prefix) so now it does not block anyone.
The MQ Server and applications are running on the same machine so imho network problems are excluded.
The queue manager error log does not report any errors but the general error log looks like this:
08/02/2016 15:15:23 - Process(13720.10) User([username])
Program(B.EXE) AMQ9202: Remote host 'localhost(1414)' not
available, retry later.
EXPLANATION: The attempt to allocate a conversation using TCP/IP to
host 'localhost(1414)' for channel (Exception) was not successful.
However the error may be a transitory one and it may be possible to
successfully allocate a TCP/IP conversation later.
For both application I use the same version of amqmdnet.dll: 8.0.0.4
Both programs A and B have the same target framework: 4.5
While testing I didn't tried to run the both applications in the same time and I checked in MQ Explorer if the channel is free (Inactive).
I also tried to change the name of resulting assemblies but with no effect.
Does anyone know what could cause application B to be unable to connect?
When using the hostname localhost networking is still involved, it just all happens inside the one machine. If application A is running in the same machine as your queue manager then having application A connect using the connection name localhost(1414) will certainly work but it is not necessary to make the connection like this (i.e. using TCP/IP) you could instead make a local bindings connection.
On the other hand, if you are using TCP/IP because application B is running on a different machine to where the queue manager is running, then using localhost(1414) will not work because localhost on one machine does not connect to localhost on another machine. You should change what is specified in the application's connection name from localhost(1414) to use the IP address (or hostname) of the queue manager's machine (followed as before with the port number).
Although I was unable to find the cause of the problem the solution was to simply
delete and re-create the project.
This is what I tried before and what led me to this action:
In B I removed and then added back the reference to amqmdnet.dll - not working
I created yet another project (let's call it C): console application, same code - working
I renamed* the C project with the same name as B - still working
*The name of the non-working project contained a dot so I thought that this could cause the problem - it was not the case.

Two unique named pipes conflicting and InvalidCredentialException

There are two problems I ran into last night which I have resolved now, but I am not 100% sure as to why what I have done has resolved them and was hoping maybe someone could offer some insight as I've been turning over a lot of rocks and have had no luck!
First Problem
The first issue is that I had two uniquely named pipes that were in two separate programs:
net.pipe://localhost/superuniquepipe1
net.pipe://localhost/superuniquepipe2
However, the second program to launch would throw an exception (I believe it was AddressAlreadyInUseException) when opening the ServiceHost due to the address already being in use.
The way I was instantiating these ServiceHosts was as follows:
Uri[] baseAddresses = new Uri[] { new Uri("net.pipe://localhost") };
this.host = new ServiceHost(this, baseAddresses);
this.host.AddServiceEndpoint(typeof(IHostType), new NetNamedPipeBinding(), "superuniquepipe1");
this.host.Open();
So I'd specify the base address of localhost first, and then specify the rest of it when adding the endpoint, the way I resolved this was to change the code as follows:
this.host = new ServiceHost(this);
this.host.AddServiceEndpoint(typeof(IHostType), new NetNamedPipeBinding(), "net.pipe://localhost/superuniquepipe2");
this.host.Open();
Am I correct in saying the reason this worked is because it was checking only the base addresses and not the endpoint I was trying to add? And is using the second code sample a valid / safe way to have multiple programs listening on "localhost"?
Second Problem:
In an attempt to fix the above, I had changed the base address from localhost to a number of different unique strings e.g. "net.pipe://rawrwhyisntthisworkingsadface", but when doing this I'd be presented with an InvalidCredentialException from the client trying to establish a connection (see below code)
I was under the impression a named pipe can literally be named anything, can anyone shed some light on this one?
ChannelFactory<IHostType> factory = new ChannelFactory<IHostType>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://rawrwhyisntthisworkingsadface/superuniquepipe2"));
IHostType proxy = factory.CreateChannel();
proxy.CallSomeMethodAndGetAnException();
Any input would be greatly appreciated, as I said I have resolved the issue and just want to know why my solution worked, but if you see a flaw in how I've resolved it and can suggest a better way of doing it please do so :)
Re problem 1:
The WCF NetNamedPipeBinding uses a named shared memory section to publish to its clients the actual name of the pipe over which the service can be called. The pipe name itself is a GUID, generated afresh each time the service host is opened. It is the name of the shared memory section used to publish the service which is dependant on the service URL. If a base address is defined, the base address is used to derive this name.
This means you can only ever have one WCF service application at a time running which uses a particular base address for its NetNamedPipe endpoints. If you try to start a second one, it fails with AddressAlreadyInUseException because it finds that the name WCF wants to use for the publishing location (derived from the base address) has already been taken by another application.
If you specify no base address, and give each service an absolute, unique service URL, then the name of the publishing location is now derived from the full absolute URL, and there is no name clash between the applications. This is an entirely valid and safe way to have multiple WCF named pipe services listening.
Re problem 2:
On the service side you can use anything for the host name part of the service URL. This is due to the HostNameComparisonMode setting applied by default in the NetNamePipeBinding, since the algorithm in WCF which derives the name for the shared memory publishing location substitutes a wildcard character for the host name see here to enable the configured host name comparison mode to be implemented.
On the client side, however, the service URL is constrained: the host part must genuinely resolve to localhost (i.e. it is localhost, the correct IP address, or the correct machine name).

How can I get the listening address/port of a WCF service?

I have a WCF service listening on a dynamic allocated port in windows Service Registry.
How can i find the listening address of this service from another c# application? Or at least the port of this service?
Thanks,
Adriana
You can dump the actual "Listeners" from inside your service implementation after the ServiceHost is open, using the "ChannelDispatcher" property.
For example:
foreach (var channelDispatcher in serviceHost.ChannelDispatchers)
{
Console.WriteLine(channelDispatcher.Listener.Uri);
}
A listener's URI will contain the TCP/IP port the service is listenting on. Note that this is of course only true for such bindings that are based on TCP/IP in the first place. Note also that obviously each service could have multiple listeners (or listener ports), hence the "ChannelDispatchers" property may return multiple listeners.
You may also want to look at / dump the value of the "State" property to make sure that the respective channel dispatcher is actuall "Open", i.e. listening.
Edit: You may also want to have look into enabling WMI for WCF. Though I never looked into it, it might reveal such information as well.
If you cannot modify the service's code, or don't want to, you need to resort to tools like "Process Explorer" or "netstat" (the later again assuming you're using some TCP/IP based binding for the service's endpoints). Use netstat's "-b" option to display the PID and executable name for each port. That will give you a hint to your service (executable).

Categories

Resources