I have a program that run in a loop, each iteration runs in a different thread and I'm creating new process that open new service host:
ServiceHost _host = new ServiceHost(_service, new Uri("net.pipe://localhost/" + i_PipeName));
_host.AddServiceEndpoint(typeof(ICommandService), new NetNamedPipeBinding() { TransferMode = TransferMode.Buffered }, i_PipeName);
_host.Open();
from my main program I connect to the open .net pipe at the following way:
ICommandService ServiceProxy = ChannelFactory<ICommandService>.CreateChannel
(new NetNamedPipeBinding(), new EndpointAddress(#"net.pipe://localhost/" + i_PipeName" + #"/" + i_PipeName));
So my problem is that for the first 200+ proccess/iterations it working fine, I can open connection and pass messages but later on there errors that starts to appear:
There was no endpoint listening at
net.pipe://localhost/pipea0360/pipea0360 that could accept the
message. This is often caused by an incorrect address or SOAP action.
See InnerException if present, for more details.
My question is if there are any limitations on the number of pipes I can open in parallel?
Is this because I open so many proccesses?
Have you ruled out a race condition, where the client is attempting to connect to a pipe that the server hasn't established yet? If you have a lot of active threads on the server, it could easily delay the thread that is supposed to start listening. That could explain why it works in the beginning.
In general, having a server thread for each client doesn't scale well; you'll get better performance with a thread pool approach.
Related
I develop a very simple app using RabbitMQ. One machine, multiple queues and exchanges, one publisher and one consumer. After reading further about Clustering and HA I connect a second machine to create a cluster, besides I mirrored queues to have at least one replica. Now when I want to publish some data into a queue, I use the first machine as my host and it works fine, but if RabbitMQ service of the first machine not running my app crashed. My question is how to know which machine is up for creating connection and how to change the host while publishing messages?
UPDATEI use one of CreateConnection overloads to pass all my hosts for creating a connection. OK, this will solve the problem of finding an available machine to create a connection. But the second question is still there, look at the code below:
for(int i = 0, i < 300, i++){
var message = string.Format("Message #{0}: {1}", i, Guid.NewGuid());
var messageBodyTypes = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(ExchangeName, "123456", null, messageBodyBytes);
}
These lines of code is work perfect when the connection is OK, but assume that in the middle of publishing messages to an exchange, the service stopped unexpectedly, then in this case first System.IO.FileLoadException raised and if I continue the executation RabbitMQ.Client.Exceptions.AlreadyClosedException raised which is saying:
Already closed: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=320, text="CONNECTION_FORCED - broker forced connection closure with reason 'shutdown'", classId=0, methidId=0, cause=
I think there must be a way to change the host when the connection closed during publishing messages, but how, no IDEA!
These lines of code is work perfect when the connection is OK, but
assume that in the middle of publishing messages to an exchange, the
service stopped unexpectedly, then in this case first
System.IO.FileLoadException raised and if I continue the executation
RabbitMQ.Client.Exceptions.AlreadyClosedException raised which is
saying:
You must close the channel and current connection and open a new one of each mid-loop. That should use a different connection. You only have to do this when the exception is caught, not on every iteration of the loop.
NOTE: the RabbitMQ team monitors the rabbitmq-users mailing list and only sometimes answers questions on StackOverflow.
I have a console program that runs perpetually to process background jobs. Every day, it uploads files via FTP to other servers. After a while it will begin to fail to transfer files with:
SocketException: System.Net.Sockets.SocketException: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full
Rebooting the server solves the issue but it's annoying. Other answers (like this one) suggest maybe my sockets are not being closed after use but I would expect FtpClient.Dispose() to take care of this, since it does not expose a .Close() method. Here's my code:
using (FtpClient client = new FtpClient())
{
client.Host = "ftp.host.com";
client.Credentials = new System.Net.NetworkCredential(userName: "foo", password: "bar");
client.Connect();
client.UploadFile(localPath: localPath, remotePath: remotePath, overwrite: true);
client.Disconnect();
}
Are there other possible causes for this error that I should investigate?
I am trying to establish a .Net remoting call to a thirdparty app. Here's the example code I have been given for that connection (With proprietary names removed):
IDictionary props = new ListDictionary();
props["port"] = 0; // have the Remoting system pick a unique listening port (required for callbacks)
props["name"] = string.Empty; // have the Remoting system pick a unique name
BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
_channel = new TcpChannel(props, new BinaryClientFormatterSinkProvider(), serverProv);
ChannelServices.RegisterChannel(_channel, true);
IThirdparty _thirdparty = (IThirdparty)Activator.GetObject(typeof(IThirdparty), "tcp://localhost:9090/Thirdparty.AppIntegration");
//Example API call
_thirdparty.Minimized = !_thirdparty.Minimized;
When this code gets called normally, it hangs at _thirdparty.Minimized and outputs a SocketException in the diagnostics window with the message:
No connection could be made because the target machine actively refused it
The call only returns if I close the Thirdparty app.
I checked netstat -bano and the only app running on port 9090 is the one I am trying to connect to.
So I moved the call to the first few lines of the Main() function in my app and it works just fine. Problem is, that's not where it's supposed to be.
My app contains a lot of other remoting calls to a different server (not on port 9090) as well as a WCF service. My guess is that one of these things are interfering.
Any ideas on how I can figure out why this remoting call never returns?
Update:
I have determined that the SocketException is likely a red herring as these exceptions are created when it works in the 3rd party test app. Also, it looks like the reason why it is hanging is because it is waiting for a Socket.Read() which never gets any data.
It turns out, in .NET remoting, there can only be one TCPClientChannel per AppDomain. Activator.GetObject() uses the first channel that was registered.
The reason why this was blocking is because I already had a TCPClientChannel setup in my AppDomain. This channel had the secure set to false when it was registered. i.e.
ChannelServices.RegisterChannel(_channel, false);
The service I was trying to talk to had security enabled and therefore the remoting call would hang trying to listen to a response that would never come.
The solution is to load my integration into a new AppDomain so that I can configure the TCPChannel differently.
I have a client using NamedPipeClientStream and a server using NamedPipeServerStream.
The client may start before the server, and when it call clientStream.Connect(timeout) i get TimeoutException as expected.
Is there any way I can check if there is a NamedPipeServerStream listening before calling the Connect to prevent an exception?
If someone bumps into this question five years later, this might be helpful:
var isPipeRunning = Directory.GetFiles( #"\\.\pipe\" ).Contains( $"\\.\pipe\{pipeName}" )
I suggest you should use an EventWaitHandle. On all clients, call WaitOne () and on server after opening the stream, call Set ().
So, on "server" side, write this:
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, String.Format(#"Global\{0}", "SERVER_OPENED_HANDLE"));
OpenStream (); // inside this method you would have code that opens your named pipe for incomming messages
// finally, signal that you are done
handle.Set ();
On client side, write something like this:
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, String.Format(#"Global\{0}", "SERVER_OPENED_HANDLE"));
// here your thread will sleep until the server calls "Set"
handle.WaitOne ();
// then you can safelly connect to the server here
ConnectToServer ();
There remains just a few situations to handle:
1) The pipe can't be opened on server becase there is already an opened pipe with the same name (will throw an exception).
2) You successfully opened the pipe, you notified clients that you are ready but after that, a milisecond after, the server crushes from some unexpected reason and the client cannot reach the server.
3) User rights problems
In all these situations, you should handle these exceptions using a try / catch and normally, if all goes well, this code will ensure that the client will NOT try to connect before the server successfully opened the pipe.
Anyway, I suggest using a more advanced technique for making IPC through Named Pipes such as using WCF or even .NET Remoting wich besides the fact that it's somehow considered obsolete by many (don't include me) is very decent at least for IPC communication. This will give you the freedom and scalability (maybe one day you will need your clients to be able to reside on other machines, and you will have to switch from IPC to a LAN communication or even in WAN / internet).
There is no way to check this only using a NamedPipeClientStream. However, you can use a Mutex like so
// In the server
var mutex = new System.Threading.Mutex(false, "MyPipeMutex");
OpenPipeAndRunServer();
mutex.Close();
// In the client process
var mutex = new System.Threading.Mutex(false, "MyPipeMutex");
if (!mutex.WaitOne(0, false))
{
OpenPipe();
}
mutex.Close();
You will probably want to wrap the Close calls in a try-finally block to make sure it always closes. In the client you can use a different timeout to actually wait for the NamedPipe to be opened.
You can also catch the exception as a work around.
Error:
Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall
Situation
There is a TCP Server
My web application connects to this TCP Server
Using the below code:
TcpClientInfo = new TcpClient();
_result = TcpClientInfo.BeginConnect(<serverAddress>,<portNumber>, null, null);
bool success = _result.AsyncWaitHandle.WaitOne(20000, true);
if (!success)
{
TcpClientInfo.Close();
throw new Exception("Connection Timeout: Failed to establish connection.");
}
NetworkStreamInfo = TcpClientInfo.GetStream();
NetworkStreamInfo.ReadTimeout = 20000;
2 Users use the same application from two different location to access information from this server at the SAME TIME
Server takes around 2sec to reply
Both Connect
But One of the user gets above error
"Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall"
when trying to read data from stream
How can I resolve this issue?
Use a better way of connecting to the server
Can't because it's a server issue
if a server issue, how should the server handle request to avoid this problem
This looks Windows-specific to me, which isn't my strong point, but...
You don't show us the server code, only the client code. I can only assume, then, that your server code accepts a socket connection, does its magic, sends something back, and closes the client connection. If this is your case, then that's the problem.
The accept() call is a blocking one that waits for the next client connection attempt and binds to it. There may be a queue of connection attempts created and administered by the OS, but it can still only accept one connection at a time.
If you want to be able to handle multiple simultaneous requests, you have to change your server to call accept(), and when a new connection comes in, launch a worker thread/process to handle the request and go back to the top of the loop where the accept() is. So the main loop hands off the actual work to another thread/process so it can get back to the business of waiting for the next connection attempt.
Real server applications are more complex than this. They launch a bunch of "worker bee" threads/processes in a pool and reuse them for future requests. Web servers do this, for instance.
If my assumptions about your server code are wrong, please enlighten us as to what it looks like.
Just a thought.
If your server takes 2seconds to response, shouldn't the Timeout values be 2000, instead of 20000 (which is 20 seconds)? First argument for AsyncWaitHandle.WaitOne() is in milliseconds.
If you are waiting 20 seconds, may be your server is disconnecting you for being idle?