0

There is a TCP server project I'm working on. It asynchronously listens the specified port for connections, accepts new connections and begins to wait for data from them. Each new client sends its ID when it connects, this way I know which socket belongs to which client.

Minimum of 100000 clients are going to be connected to the server at the same time.

The question is how should I store these clients?

class Client
{
    public Socket Socket { get; set; }
    public int ID { get; set; }
}

Something like List<Client> would definitely break since List<T> is not a thread-safe type. I should add the client to the list when it connects to the server, remove it from the list when the connection is lost. I also need to be able to send a message to the client with the ID of 5, for example and iterating a List<T> in an asynchronous environment is a terrible idea. I think locking a sync root every time that I need to interact with the collection wouldn't do any good when it comes to performance.

So, what should I use for performance?

Edit: I use .NET 4

Şafak Gür
  • 7,045
  • 5
  • 59
  • 96

2 Answers2

3

I would use a thread-safe dictionary with the ID as the key. If you're using .net 4 you can use the System.Collections.Concurrent.ConcurrentDictionary - if not you can either roll your own or check out this url for a nice one that uses reader/writer locks

http://devplanet.com/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx

Toby Couchman
  • 522
  • 4
  • 14
0

Instead of List<Client> you should use Dictionary<int, Client>. By this you can access client of any id with single line of code e.g.

 Dictionary<int, Client> connected = new Dictionary<int, Client>();
 Client cc = connected[5];
 byte[] data = new byte[100]; // any data here
 cc.SendData(data);
Waqar
  • 2,511
  • 18
  • 15
  • Just remember when you are iterating through collection and at that time some thing is added or removed then exception will be thrown that collection is modified. – Waqar Jul 02 '12 at 12:14
  • 1
    Consider to use ConcurrentDictionary if you want to be thread-safe and do not want to lock on your own. – weismat Jul 02 '12 at 12:19
  • I don't need to iterate it as long as I can get the client using its key/ID. (I don't know how the indexer gets it, though. Doesn't it iterate?). Adding and removing items are also the case, server is constantly listening for new connections. What do you recommend for this? Using locks? @weismat, I saw Toby's answer too but when Waqar said that the standard dictionary is thread-safe, I wanted to know how thread-safe it is before deciding which one would be better. – Şafak Gür Jul 02 '12 at 12:28
  • Under the Title Thread Safety it is written "A Dictionary can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with write accesses, the collection must be locked during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization". Now choice is yours – Waqar Jul 02 '12 at 12:53
  • 1
    you should also consider for ConcurrentDictionary. – Waqar Jul 02 '12 at 12:55
  • 1
    The generic dictionary is definitely not thread-safe in your scenario - you will almost certainly find situations where an entry is being added/removed at the same time you are indexing into the dictionary in order to send a message to a client. Here's an msdn blog about the dictionary thread-safety: http://blogs.msdn.com/b/kimhamil/archive/2008/03/08/hashtable-and-dictionary-thread-safety-considerations.aspx As you can see, if your dictionary was re-sizing at the same moment a TryGetValue was called, the TryGet could return the wrong value, and you could send a message to the wrong client! – Toby Couchman Jul 03 '12 at 08:55