I have been working with the following code published on msdn:
http://msdn.microsoft.com/en-us/library/fx6588te.aspx
I understand that the server application is not blocked whilst the application is waiting for new clients.
However can this application (or even sockets) for that matter handle multiple concurrent requests?
What would happen if client A and B connected at the same time?
If client A connects and the handling of its request takes 5 seconds, if client B connects a second later must it wait for client A to finish before its processing can start?
Or will client A and client B's requests be handled concurrently?
I have done some testing with this by putting Thread.Sleep(n) commands in between the receive/send data in the socket listener code. I can then send multiple requests to the socket and they appear to be handled. However the socket always handles them on the same thread id - which makes me believe that it isnt actually happening concurrently.
Especially given the description by microsoft that this app simply doesnt block whilst awaiting for new connections - does that mean it can handle concurrent connections?
[Update 2014]: It seems that the example has been modified since this answer was posted, as noted in this thread. The MSDN example now handles multiple incoming connections properly. Anyway, the general approach described here is correct and perhaps it can provide additional clarification.
When doing socket communication, you basically have a single listener socket for all incoming connections, and multiple handler sockets for each connected client.
Listening to incoming connections
When you start listening to a port, you create a socket with a callback method for incoming connections (this is referencing the example you mentioned). That's the one-and-only listener socket for that port number:
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
This line tells the listener to invoke the AcceptCallback method whenever a new client is connected (new connection callback). That method is the one which should do its work quickly, since it blocks other incoming connections.
Creating dedicated handler sockets
That is also why AcceptCallback must immediately create a dedicated "handler" socket with its own background data callback method (ReadCallback):
// inside AcceptCallback, we switch to the handler socket for communication
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state); // fired on a background thread
From that moment on, ReadCallback method is invoked whenever some data is received by your newly connected client.
Also, before returning, AcceptCallback needs to call listener.BeginAccept again, to continue listening to new incoming connections:
// this is the same server socket we opened previously, which will now
// continue waiting for other client connections: it doesn't care about
// the actual data transmission between individual clients
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
This part is omitted from the MSDN example, meaning it can only receive a single connection.
Receiving data
As soon as you get a packet of data from your client, ReadCallback method will be invoked. So, inside this data callback method, you need to read and process the received data, and then invoke the same BeginReceive method again (again, with ReadCallback as its data callback method).
[Edit]
The problem with MSDN example is that it allows connection of only a single client (listener.BeginAccept is called only once). To allow mulitple concurrent connections, you need to create a receive socket using handler.BeginReceive, and then call listener.BeginAccept to start listening to new clients.
Every socket will have a listen queue associated with it. This will have the pending/partially accepted incoming connections. The max number number of pending connections can be defined programmatically in listen() API, which is nothing but 'listener.Listen(100)' in this example. Having had this as 100 here, the socket 'listener' can have 150 (=2*100/2) pending connections in the listen queue.
Related
My socket server initialize X amount of clients on a pool, on a new connection I get one from the pool and start listening on a new task. When a message is received, that client get the socket message and run a new Task that manage the received data while it go back to keep receiving.
I think I am collision safe between clients, but if a client receive the same type of message fast enough the second one could use the same method the first message is running asynchronously.
Should I externalize managing the action to a new class and initialize a pool of "ActionManagers" so each message have his own and only care when they update a shared resource? Any better idea?
I'm using a TcpClient and calling Close when I want to drop the client's connection to my server. My understanding is that Close will call Shutdown on the socket if it hasn't already been called.
Can anyone explain what "terminated" means in the context below? From what I've observered, it means that the party that calls Shutdown will send a hard reset (RST) rather than going through the graceful shutdown sequence (FIN, ACK...).
From: https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.shutdown(v=vs.110).aspx
Setting how to Receive specifies that subsequent calls to Receive are
not allowed. This has no effect on lower protocol layers. If you are
using a connection-oriented protocol, the connection is terminated if
either of the following conditions exist after a call to Shutdown :
Data is in the incoming network buffer waiting to be received.
More data has arrived.
Based on this, if I wanted to do a graceful shutdown I must try to empty my local receiving buffer before calling Close.
Is that right or is there a way to guarantee a graceful shutdown occurs?
A graceful shutdown is done by first shutting down your outgoing channel socket.Shutdown(SocketShutdown.Send)), and keep reading on the socket.
The other side will read your shutdown request as a 0-byte message, and after sending all remaining data it should respond by closing its socket. This causes your side to receive a 0 byte message, ending the transaction.
I have a problem with sockets. This:
When client-thread ends, server trying to read, and its freezes, because socket is not closed. Thread dont close it, when its over. Its problem exist, if i using thread, but if i using two independents projects, i have no problem (exception throws, and i can catch it).
I cant use timeout, and i must correct continue server-work, when client dont close socket.
Sorry for my bad eng.
As far as I know, there is no way for TCP server (listener) to find out whether data from client are not coming because it has died/quit or is just inactive. This is not .NET's defficiency, it is how TCP works. The way I deal with it is:
1. Create a timer in my client that periodically sends signal "I am alive" to the server. For example, I just send 1 unusual ASCII character '∩' (code 239).
2. In TCP listener: use NetworkStream.Read(...) method that allows to specify timeout. If timeout expires, the server disposes the old NetworkStream instance and creates new one on the same TCP port. If the server receives "I am alive" signal from client, it keeps listening.
By the way, the property TcpClient.Connected is useless for detecting on server side whether client still uses the socket. The method only returns true if last Read action returned something. So, if client is alive and just silent, the TcpClient.Connected becomes false.
Close client when you want the connection to be closed (at the end of Client).
Better yet, use using for all disposable resources such as both clients and the listener.
I am trying to write a c# server/client that will simultaneously send byte arrays over TCP across each other. I'm trying to wrap my head around how to accomplish this. All of the example I have seen wait for a message, then send a response. I need communication to happen simultaneously.
Would I need to create 2 separate TCP socket connections for ingoing & outgoing on both the server & client? Can I pass data simultaneously with 1 connection in a "full duplex" fashion? Any help is appreciated.
I would advise you to look at the asynchronous sockets. The reason is, that they don't block threads while receiving or sending data.
Socket.BeginReceive(buffer, offset, size, endReceiveMethod);
The endreceive method will be called when there are bytes received. (on a other thread)
This is the same for sending.
Socket.BeginSend(buffer, offset, size, endSendMethod);
I remember in the early days I was worried about reading and writing on the same thread, creating difficult constructions with read-timeouts etc and each client it's own thread.
This isn't needed with Asynchronous sockets. It doesn't use a single thread per client. It uses I/O Completion Ports http://msdn.microsoft.com/en-us/library/windows/desktop/aa365198(v=vs.85).aspx instead of blocking threads.
You should look into using select() method to listen on server and client file descriptor (or fd). http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.select.aspx
Basically, if you have a TCP server, let us say, fd0 and if the client sends a connect, then the server fd would create a new fd for the new connection, let us call it fd1. Now, you would want to do three things with these: (a) listen for newer incoming connections on fd0, (b) wait for reciving data on fd1, and (c) send data on fd1. Sending data is usually non-blocking, so you dont have to worry about that. But, for (a) and (b), you can use a select.. If there is data to be read on fd1, then you would get a read event. Likewise, if there is a new connection on fd0, then also you would get a read event and you can call accept.
I am currently creating a Windows Service that will create TCP connections to multiple machines (same socket on all machines) and then listen for 'events' from those machines. I am attempting to write the code to create a connection and then spawn a thread that listens to the connection waiting for packets from the machine, then decode the packets that come through, and call a function depending on the payload of the packet.
The problem is I'm not entirely sure how to do that in C#. Does anyone have any helpful suggestions or links that might help me do this?
Thanks in advance for any help!
Depending on how many concurrent clients you plan on supporting, a thread-per-connection architecture will probably break down very quickly. Reason being, each thread requires significant resources. By default each .NET thread gets 1MB of stack space so that's 1MB per connection plus any overhead.
Instead when supporting multiple connected clients typically you will use the asynchronous methods (see here also) which are very efficient because Windows will use "completion ports" which basically free up the thread to do other things while waiting on some event to complete.
For this you would look at methods such as BeginAccept, BeginReceive, BeginSend, etc.
A simpler approach which also avoids making blocking calls and avoids multiple threads is to use the Socket.Select method in a loop. This allows a single thread to service multiple sockets. The thread can only physically read or write to a single socket at a time but the idea is that you are checking the state of multiple sockets which may or may not contain data to read.
In any case, the thread-per-connection approach is much simpler to get your head around at first, but it does have significant scalability problems. I would suggest doing that first with the synchronous methods like Accept, Receive, Send, etc. Then later on refactor your code to use the asynchronous methods so that you don't exhaust the server's memory.
You can have asynchronous receive for every socket connection and decode the data coming from other machines to perform your tasks (You can find some useful information about asynchronous methods here: http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx).
To create a connection, you can do:
Socket sock = Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Connect(new IPEndPoint(address, port));
Same way you can create multiple connections and keep there references in a List of Dictionary (whichever you prefer).
For receiving data asynchronously on a socket, you can do:
sock.BeginReceive(buffer, 0, buffer.len, SocketFlags.None, new AsyncCallback(OnDataReceived), null);
The method OnDataReceived will be called when receive operation completes.
In OnDataReceived method you have to do:
void OnDataReceived(IAsyncResult result)
{
int dataReceived = sock.EndReceive(result);
//Make sure that dataReceived is equal to amount of data you wanted to receive. If it is
//less then the data you wanted, you can do synchronous receive to read remaining data.
//When all of the data is recieved, call BeginReceive again to receive more data
//... Do your decoding and call the method ...//
}
I hope this helps you.
Have a single thread that runs the accept() to pick up new connections. For each new connection you get, spawn a worker thread using the thread pool.
I don't know if it's possible in your situation but have you thought about using a WCF service that gets called by the multiple machines ? You can host this in a custom windows service or IIS. It will consume very little resource while waiting for events and it's much simpler to code than all that low level scary socket stuff. It's automatically async. You get nice messages to your service rather than a packet you need to deserialize and/or parse. You can use any number of protocols such as REST or binary.
You will of course need to create the process on the other end that sends the messages.
Just a thought...
Cheers