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.
Related
I'd like to use NamedPipeClientStream:
var _Pipe = new NamedPipeClientStream(".", "test-a", PipeDirection.In);
_Pipe.Connect();
Unfortunately, there is no way to pass Cancellation token. So, how to cancel connection? I don't want to pass timeout - my client needs to wait "forever" until connection is successful or cancel is requested. ConnectAsyncis not available.
EDIT:
I am using .NET Frameowkr 4.5.2 Class library, and there is no such a method like ConnectAsync (only Connect is available).
To cancel, call Close() or Dispose() method on that pipe. If you'll need to retry later, just create another pipe for that.
I’m 90% sure the thread that was sleeping on that Connect() call will wake up immediately, and fail with some exception. Probably ObjectDisposedException if you call Dispose, or some "The pipe is being closed." Win32 exception if you call Close().
I have never tested with pipes specifically, but that’s what usually happens in Windows with blocking I/O calls for files and sockets.
Hello and thanks for your help.
This time I would like to ask about TcpClient.
I have a server program and I am writing a client program.
This client uses TcpClient. It starts by creating a new client
clientSocket=new TcpClient();
(By the way, can this cause exceptions? just in case I put it inside a try-catch but I am not sure if that is really necessary)
Anyway, later I enter a loop and inside this loop I connect to the server
clientSocket.Connect("xx.xx.xx.xx",port);
Then I create a NetworkStream with
clientStream=clientSocket.GetStream();
and then start waiting for data from the server through Read. I know this is blocking so I also set a ReadTimeOut (say 1 second)
Anyway, so far so good.
Later if I don't receive anything from the server, I attempt to send something to it. If this keeps happening for say 3 times I want to close the connection and reconnect to the server again
(notice that a whole different problem is when the server somehow is down, cause that causes other kinds of errors in the client-perhaps I will ask about that later)
So, what do I do?
if(clientSocket.Connected)
{
Console.WriteLine("Closing the socket");
clientSocket.Close();
}
I close the socket.
The loop is finished so I go again to the beginning and try to connect to the server.
clientSocket.Connect("xx.xx.xx.xx",port);
However this causes an error(an unhandled exception actually) "Can not access a disposed object"
So my question is How can I close and reconnect to the server again??
Thanks again for any help
A TcpClient instance can only be used to connect once. You can simply instantiate a new TcpClient, rather than trying to re-open a closed one.
As explained in the other answer, a TcpClient object can only be connected once. If you want to reconnect to the server, you have to create a new TcpClient object and call Connect() again.
That said, you have a number of apparent misconceptions in your question:
First and most important, you should not use ReceiveTimeout if you have any intention whatsoever of trying to use the TcpClient object again, e.g. to send some data to the server. Once the timeout period has expired, the underlying socket is no longer usable.If you want to periodically send data to the server when the server hasn't sent data to you, you should use asynchronous I/O (which you should do anyway, in spite of the learning curve) and use a regular timer object to keep track of how long it's been since you received data from the server.
The TcpClient constructor certainly can throw an exception. At the very least, any attempt to new a reference type object could throw OutOfMemoryException, and in the case of TcpClient, it ultimately tries to create a native socket handle, which could also fail.While all I/O objects and methods can throw exceptions, you should only ever catch exceptions that you have a way to handle gracefully. So before you add a try/catch block to your code, decide what it is you want to do in the case of an exception that will ensure that your code doesn't corrupt any data and continues to operate correctly. It is generally not possible to gracefully handle OutOfMemoryException (and impractical to protect all uses of new in any case), but you certainly can catch SocketException, which could be thrown by the constructor. If that exception is thrown, you should immediately abandon the attempt to create and use TcpClient, and report the error the user so that they can attempt to correct whatever problem prevented the socket's creation.
If your server is expected to be sending you data, and you don't receive it, then closing the connection and retrying is unlikely to improve the situation. That will only cause additional load on the server, making it even more likely it will fail to respond. Likewise sending the same data over and over. You should your request once, wait as long as is practical for a response from the server, and if you get no response within the desired time, report the error to the user and let them decide what to do next.Note that in this case, you could use the ReceiveTimeout property, because all you're going to do if you don't get a response in time is abandon the connection, which is fine.
Very simple:
client.Close();
client = new TcpClient();
client.Connect(host, port);
I am using multithreaded server to handle client communication, I don't know how many clients can this server handle. If number of clients increase will it be able to handle them? I am using it on core2duo processor.
Will starting server on different port solve the problem, if i redirect half of the clients to new server with another port?
Here is my code for server
Public void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
try
{
TcpClient client = this.tcpListener.AcceptTcpClient();
NetworkStream clientStream = client.GetStream(); //create networkstream for connected client
Console.WriteLine(((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());//client ipaddress
Console.WriteLine("connecting..");
Thread clientThread = new Thread(new ParameterizedThreadStart(updatedb));
clientThread.Start(client);
}
catch (Exception ex)
{
Console.WriteLine("exception" + ex.ToString());
Console.ReadLine();
}
}
}
I suggest you read this blog post and similar posts by the author. He explains there in great detail how multi threading is used by IIS / ASP.NET.
What you must remember, is that even if You can create more threads (by running anothre instance of your application, as you suggested, for example), it doesnt mean your application will be more responsive / return the expected answers to the clients faster, as there can be only as much running threads at any given moment as the number of CPUS your server has.
I dont think you need to write your code in an expectation of collapsing, but to work in a direction of more of an async processing, as the ISS server (which is practically doing the same - servicing TCP connections) is doing. Theres no reason not to use the thread pool provided by .NET, let it handle the real number of co-existing threads at every given moment, and let the other requests queue untill a thread becomes availibale.
Without actually trying it, everything else is a guess. As Hans Passant says, your strategy of creating a new thread for every request will not scale well. It may seem ok at first, but you should see performance fall off badly over a few hundred simultaneous users. In addition, it looks like the work will be communicating with a database (updatedb), so these threads you've created will just be sending data to an external process and waiting for a reply? That's the worst use of a thread. See if you can use asynchronous sql updates.
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?
What is the correct way to close or reset a TcpClient connection?
We have software that communicates with hardware but sometimes something
goes wrong and we are no longer to communicate with it, until we restart the software.
I have tried forcing TcpClient.Close() and even setting it to null but that doesn't work.
Only a complete restart of the software works.
Suggestions?
I can't use the using keyword because TpcClient is only defined in one location, but used throughout the library. (And there is only one connection at any given time)
It's a library that handles communication. The software itself can call the ResetConnection() method of the Controller class (which represents the hardware).
It currently looks like
if (tcpClient != null)
{
tcpClient.Close();
tcpClient = null;
}
Now from what I've read here I should use tcpClient.Dispose() instead of " = null"
I'll give that a try and see if it makes a difference.
You have to close the stream before closing the connection:
tcpClient.GetStream().Close();
tcpClient.Close();
Closing the client does not close the stream.
Given that the accepted answer is outdated and I see nothing in the other answers regarding this I am creating a new one. In .Net 2, and earlier, you had to manually close the stream before closing the connection. That bug is fixed in all later versions of TcpClient in C# and as stated in the doc of the Close method a call to the method Close closes both the connection and the stream
EDIT according to Microsoft Docs
The Close method marks the instance as disposed and requests that the
associated Socket close the TCP connection. Based on the LingerState
property, the TCP connection may stay open for some time after the
Close method is called when data remains to be sent. There is no
notification provided when the underlying connection has completed
closing.
Calling this method will eventually result in the close of the associated Socket and will also close the associated NetworkStream that is used to send and receive data if one was created.
Use word: using. A good habit of programming.
using (TcpClient tcpClient = new TcpClient())
{
//operations
tcpClient.Close();
}
Despite having all the appropriate using statements, calling Close, having some exponential back off logic and recreating the TcpClient I've still been seeing issues where the application cannot recover the TCP connection without an application restart. It keeps failing with a
System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
But there is an option LingerState on the TcpClient that appears it may have solved the issue (might not know for a few months as my own hardware setup only fails about that often!). See MSDN.
// This discards any pending data and Winsock resets the connection.
LingerOption lingerOption = new LingerOption(true, 0);
using (var tcpClient = new TcpClient
{SendTimeout = 2000, ReceiveTimeout = 2000, LingerState = lingerOption })
...
Except for some internal logging, Close == Dispose.
Dispose calls tcpClient.Client.Shutdown( SocketShutdown.Both ), but its eats any errors.
Maybe if you call it directly, you can get some useful exception information.
Closes a socket connection and allows for re-use of the socket:
tcpClient.Client.Disconnect(false);
The correct way to close the socket so you can re-open is:
tcpClient.Client.Disconnect(true);
The Boolean parameter indicates if you want to reuse the socket:
Have you tried calling TcpClient.Dispose() explicitly?
And are you sure that you have TcpClient.Close() and TcpClient.Dispose()-ed ALL connections?
client.Dispose();
client.Close();
if (stream != null)
{
clientstream.Dispose();
clientstream.Close();
}