简体   繁体   中英

C# Asynch Socket Server Example - How to Message all clients?

Hey everyone, You guys here are awesome, I'm getting so many questions answered, its helping so much.

I have modified this example server Asynchronous Socket Server from MSDN: http://msdn.microsoft.com/en-us/library/fx6588te.aspx

I have modified it slightly and it works a treat with what I am needing to do. the issue is at the moment. That is allows the send/receive between one client at a time. I need to be able to pinpoint specific clients that are connected to said server, and send a message to them.

How can I modify the above example to include an identifier for each connection, or at least a set of identifiers so that I can send messages to whom I need to.

The clients may have around 6-10 independent variables, each need to be filtered as needed (for example, sending data to a set of clients in a group). I had an old blocking server that wasn't efficient enough, I simply had a 2 dimension array which did the job perfectly. A loop around all clients filtering the array was fine. But in the above example, the connections dont seem to be identified or stored, what would you recommend and where would it be easiest to store it?

I'm fairly new to .net and especially socket server programming. Any help would be great!

edit: I have been banging my head against a brick wall about this, I heard though of adding the variables in need within the 'state object' the issue is that it renews with each connection. I need to know who is connected so I can send messages to the connected clients!

Any idea?

We had a similar situation for one of the tools we created (I didn't work directly on it but the solution seems to work fine). Every time we received a client we stored the relevant information in a class (similar to the StateObject class in the example) and added that class to an ArrayList (which works fine) but I suppose a nicer solution would be store the classes in a Dictionary:

http://msdn.microsoft.com/en-us/library/xfhwa508.aspx

The Dictionary class allows you to map a Key to an object. This allows you to easily access objects using a unique key. So on receiving a new client you could create an ID for that client which ever way you wish (this might just be an integer which increments every time a client connects), create a state object class and store the relevant information you need within that class, then add the Key Class pair to the dictionary, so something similar to:

// Global definition of Client dictionary
// The first argument within <> is the key type, the second argument
// is the type of object that key will map to
Dictionary<int, StateObject> Clients = new Dictionary<int, StateObject>();

// Accept client callback
public static void AcceptCallback(IAsyncResult ar)
{
    // Get the socket that handles the client request.
    Socket listener = (Socket) ar.AsyncState;
    Socket handler = listener.EndAccept(ar);

    StateObject client = new StateObject();

    // Then set all the variables of client here

    Clients.Add(ID, client);
}

Note: However you want to create your IDs they must be unique for each entry within the Dictionary.

My advice would be to store the handler for each accepted socket client within the StateObject. This way you always have access to a handle which can send information to each individual connected client (this is how we did it with our Tcp connection, we stored the TcpClient and its underlaying Stream in our StateObject class and then communicated with each client through these variables. I'm assuming this is possible with Sockets too?)

Now with all the information stored you could either use the ID keys within the dictionary to identify which clients to communicate with. Using LINQ gives you a nice one line select command:

// Selects state objects from Clients dictionary where ID has a value greater than 5
IEnumerable<StateObject> Clients.Where(c => c.Key > 5).Select(c => c.Value);

(I think this is the valid LINQ query but it will need checking, its essentially saying select each StateObject from the client list, where the ID is greater than 5)

If you don't want the IDs to identify clients in this way you could loop through every StateObject within the dictionary and check internal variables to see whether you send the client a message or not. Something like:

foreach (StateObject client in Clients.Values)
{
    if (client.ImportantVariable == true)
        // Send client information via socket here
}

Its really up to you to decide which method would best suit your needs. Hope this helps and is a viable solution for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM