How many client can a multi-threaded server handle? - c#

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.

Related

Check if NamedPipeClientStream write is successful

Basically the title... I'd like to have same feedback on weather NamedPipeServerStream object successfully received a value. This is the starting code:
static void Main(string[] args){
Console.WriteLine("Client running!");
NamedPipeClientStream npc = new NamedPipeClientStream("somename");
npc.Connect();
// npc.WriteTimeout = 1000; does not work, says it is not supported for this stream
byte[] message = Encoding.UTF8.GetBytes("Message");
npc.Write(message);
int response = npc.ReadByte();
Console.WriteLine("response; "+response);
}
I've implemented a small echo message from the NamedPipeServerStream on every read. I imagine I could add some async timeout to check if npc.ReadByte(); did return a value in lets say 200ms. Similar to how TCP packets are ACKed.
Is there a better way of inspecting if namedPipeClientStream.Write() was successful?
I'd like to have same feedback on weather NamedPipeServerStream object successfully received a value
The only way to know for sure that the data you sent was received and successfully processed by the client at the remote endpoint, is for your own application protocol to include such acknowledgements.
As a general rule, you can assume that if your send operations are completing successfully, the connection remains viable and the remote endpoint is getting the data. If something happens to the connection, you'll eventually get an error while sending data.
However, this assumption only goes so far. Network I/O is buffered, usually at several levels. Any of your send operations almost certainly involve doing nothing more than placing the data in a local buffer for the network layer. The method call for the operation will return as soon as the data has been buffered, without regard for whether the remote endpoint has received it (and in fact, almost never will have by the time your call returns).
So if and when such a call throws an exception or otherwise reports an error, it's entirely possible that some of the previously sent data has also been lost in transit.
How best to address this possibility depends on what you're trying to do. But in general, you should not worry about it at all. It will typically not matter if a specific transmission has been received. As long as you can continue transmitting without error, the connection is fine, and asking for acknowledgement is just unnecessary overhead.
If you want to handle the case where an error occurs, invalidating the connection, forcing you to retry, and you want to make the broader operation resumable (e.g. you're streaming some data to the remote endpoint and want to ensure all of the data has been received, without having to resend data that has already been received), then you should build into your application protocol the ability to resume, where on reconnecting the remote endpoint reports the number of bytes it's received so far, or the most recent message ID, or whatever it is your application protocol would need to understand where it needs to start sending again.
See also this very closely-related question (arguably maybe even an actual duplicate…though it doesn't mention named pipes specifically, pretty much all network I/O will involve similar issues):
Does TcpClient write method guarantees the data are delivered to server?
There's a good answer there, as well as links to even more useful Q&A in that answer.

How to Stop Server Crash when Client Crashed internally (TCP/IP Socket)

Description about the problem.
Currently I am developing server - multiple clients (over 3000 clients) application in csharp. Server and clients exchange messages. The problem is that server get crashed if any of the client crashes for the internal reason. The internal reason can include all sort of specific problem of client computer. For example, they can be the lost internet connection, the computer crash, power failure, etc.
As the server functions to deliver the real time information, if the server crashes, then entire operation stops. This is nightmare for server because we can not predict which client will crash.
The main code causing the server crashes is below:
public bool Send(byte[] buffer)
{
if (m_Socket == null)
{
return (false);
}
try
{
mSocket.Send(buffer);
return (true);
}
catch(System.Net.Sockets.SocketException ex)
{
mSocket = null;
return (false);
}
return (false);
}
I think there were few answers to the similar problem from my research. However often the answers point out the use of Keep alive packets.
I think many answer in this website indicates that detecting the half open connection (dropped connection) is almost impossible without using keep alive packet from client side.
In our application, we do not prefer to use Keep alive packet or message because the server and client communicate in milliseconds. Receiving keep alive packet or message from over 3000 clients every seconds does not seems friendly for resource management point of view for server. So we prefer to have rather a good error management. If the client computer is crashed, then we just want to ignore. I am not sure whether this can make the running server unstable ?
Anyway, I came up with few ideas with below options. It was the suggestions from other coders most of time on the net. So the question is Which option might be the best to safely catch the Socket.Send() failure error and not disturbing the operation of the server?
Using simple try catch statement. Will this offer the 100% secure fail safe operation for this problem ? From my experience, sometimes, it works but sometimes it does not work.
try
{
mSocket.Send(buffer);
return (true);
}
catch(System.Net.Sockets.SocketException ex)
{
mSocket = null;
return (false);
}
Use of while(true) loop. Someone mentioned that while(true) loop might be the safe way of doing this. However, I am not sure how effective this solution comparing to simple try catch statement.
Perform Socket.Send() function inside other thread rather than main thread. The idea is that if Socket.Send() functions fails then the thread used for Socket.send() function will terminate on its own without disturbing the main thread for the application. However, I do not have sufficient knowledge how each thread suppose to interact together. So I can not tell whether this method is better than above two methods.
Can you please suggest any idea or solution for this specific problem? I think that without using Keep alive packet, maintaining the sever operation without crash is quite challenging problem.

Way to check if NamedPipeServerStream started in Client side

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.

Confused about Sockets with UDP Protocol in C#

I've just started learning Sockets through various Google searches but I'm having some problems figuring it out how to properly use Sockets in C# and I'm in the need of some help.
I have a test application (Windows Forms) and on a different class (which is actually in it's own .dll, but that's irrelevant) I have all the server/client code for my sockets code.
Question 1)
On my test application, on the server part, the user can click the "start listening" button and the server part of my sockets application should start listening for connections on the specified address and port, so far so good.
However, the application will be blocked and I can't do anything until someone connects to the server. What if no one connects? How should I handle that? I could specify a receive timeout but what then? It throws an exception, what can I do with that? What I would like is to have some sort of activity on the main application so the user knows the application didn't froze and is waiting for connections. But if a connection doesn't come, it should timeout and close everything.
Maybe I should use asynchronous calls to send/receive methods but they seem confusing and I was not able to make it work, only synchronous work (I'll post my current code below).
Question 2)
Do I need to close anything when some send/receive call times out. As you'll see on my current code, I have a bunch of closes on the socket, but this doesn't feel right somehow. But it also doesn't feel right when an operation times out and I don't close the socket.
In conclusion of my two questions.... I would like an application that doesn't block so the user knows the server is waiting for a connection (with a little marquee animation for instance). If a connection is never established after a period of time, I want to close everything that should be closed. When a connection is established or if it doesn't happen after a period of time, I would like to inform the main application of the result.
Here's some of my code, the rest is similar. The Packet class is a custom class that represents my custom data unit, it's just a bunch of properties based on enums for now, with methods to convert them to bytes and back into properties.
The function that starts to listen for connections is something like this:
public void StartListening(string address, int port) {
try {
byte[] bufferBytes = new byte[32];
if(address.Equals("0.0.0.0")) {
udpSocket.Bind(new IPEndPoint(IPAddress.Any, port));
} else {
udpSocket.Bind(new IPEndPoint(IPAddress.Parse(address), port));
}
remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
int numBytesReceived = udpSocket.ReceiveFrom(bufferBytes, ref remoteEndPoint);
if(numBytesReceived == 0) {
udpSocket.Close();
return;
}
Packet syncPacket = new Packet(bufferBytes);
if(syncPacket.PacketType != PacketType.Control) {
udpSocket.Close();
return;
}
} catch {
if(udpSocket != null) {
udpSocket.Close();
}
}
}
I'm sure that I have a bunch of unnecessary code but I'm new at this and I'm not sure what do, any help fixing up my code and how to solve the issues above is really appreciated.
EDIT:
I should probably have stated that my requirements are to use UDP and implement these things myself in the application layer. You can consider this as homework but I haven't tagged as such because the code is irrelevant and will not be part of my grade and my problem (my question) is in "how to code" as my Sockets experience is minimal and it's not taught.
However I must say that I solved my problem for now I think... I was using threading on the demo application which was giving me some problems, now I'm using it in the protocol connections, makes more sense and I can easily change my custom protocol class properties and read those from the demo application.
I have specified a timeout and throw a SocketException if it reaches the timeout. Whenever an exception like this is caught, the socket connection is closed. I'm just talking about the connection handshake, nothing more. If no exceptions are caught, the code probably went smooth and the connection is established.
Please adapt your answers accordingly. Right now it doesn't make sense for me to marky any of them as the accepted answer, hope you understand.
You have got stuff a bit wrong.
First of all, UDP is connection-less. You do not connect or disconnect. All you do is to send and receive (must specify destination each time). You should also know that the only thing UDP promises is that a complete message arrives on each read. UDP do not guarantee that your messages arrive in the correct order or that they arrive at all.
TCP on the other hand is connection-based. You connect, send/receive and finally disconnect. TCP is stream-based (while UDP is message-based) which means that you can get a half message in the first read and the other half at the second read. TCP promises you that everything will arrive and in the correct order (or will die trying ;). So using TCP means that you should have some kind of logic to know when a complete message has arrived and a buffer that you use to build the complete message.
The next big question was about blocking. Since you are new at this, I recommend that you use Threads to handle sockets. Put the listener socket in one thread and each connecting socket in a separate thread (5 connected clients = 5 threads).
I also recommend that you use TCP since it's easier to build complete messages than ordering messages and build a transaction system (which will needed if you want to make sure that all messages arrives to/from clients).
Update
You still got UDP wrong. Close doesn't do anything other than cleaning up system resources. You should do something like this instead:
public void MySimpleServer(string address, int port)
{
try
{
byte[] bufferBytes = new byte[32];
if(address.Equals("0.0.0.0")) {
udpSocket.Bind(new IPEndPoint(IPAddress.Any, port));
} else {
udpSocket.Bind(new IPEndPoint(IPAddress.Parse(address), port));
}
remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
while (serverCanRun)
{
int numBytesReceived = udpSocket.ReceiveFrom(bufferBytes, ref remoteEndPoint);
// just means that one of the clients closed the connection using Shutdown.
// doesnt mean that we cant continue to receive.
if(numBytesReceived == 0)
continue;
// same here, loop to receive from another client.
Packet syncPacket = new Packet(bufferBytes);
if (syncPacket.PacketType != PacketType.Control)
continue;
HandlePacket(packet, endPoint);
}
} catch {
if(udpSocket != null) {
udpSocket.Close();
}
}
}
See? since there are no connection it's just waste of time to close a UDP socket to start listening from another one. The same socket can receive from ALL udp clients that know the correct port and address. That's what the remoteEndPoint is for. It tells which client that send the message.
Update 2
Small update to make a summary of all my comments.
UDP is connectionless. You can never detect if a connection have been established or disconnected. The Close method on a UDP socket will only free system resources. A call on client.Close() will not notify the server socket (as it will with TCP).
The best way to check if a connection is open is to create a ping/pong style of packet. i.e. the client sends a PING message and the server responds with a PONG. Remember that UDP will not try to resend your messages if they do not arrive. Therefore you need to resend the PING a couple of times before assuming that the server is down (if you do not receive a PONG).
As for clients closing you need to send your own message to the server telling it that the the client is going to stop talking to the server. For reliability the same thing goes here, keep resending the BYE message until you receive a reply.
imho it's mandatory that you implement a transactional system for UDP if you want reliability. SIP (google rfc3261) is an example of a protocol which uses transactions over UDP.
From your description I feel you should use TCP sockets instead of UDP. The difference is
TCP - You wait for a connection at a particuler IP:Port some user can connect to it and until the socket is closed can communicate by sending and receiveing information. This is like calling someone on phone.
UDP - you wait for a message at some IP:Port. User who wants to communicate just sends a message through UDP. You will receive the message through UDP. The order of delivery is not guaranteed. This is more like sending a snail mail to someone. There is no dedicated communication channel established.
Now coming to your problem
Server
Create a Socket with TCP family.
Either create a thread and accept the connection in that thread or use the BeginAccept apis of Socket.
In the main thread you can still display the ticker or whatever you want to do.
Client
Connect to the server.
Communicate by sending and receiving data.

Unable to make 2 parallel TCP requests to the same TCP Client

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?

Categories