If I understood the logic of BeginSend correctly:
private void sendToClient(Client client, String data)
{
byte[] byteData = Encoding.UTF8.GetBytes(data); //It must be UTF8
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(sendCallback), client);
}
private void sendCallback(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
int bytesSent = client.EndSend(iar);
}
I have sent the data to one client correctly.
But if I want to send the data for more clients:
/**
* I am using dictionary, because I hold the clients with login-key
*/
private void SendToClients(Dictionary<string, Client> connectedClients, String data)
{
foreach(Client client in connectedClients.Values)
{
sendToClient(client, data);
}
}
Or in anotherway, I can use SocketAsyncEventArgs to send all clients:
private void sendToClients(Dictionary<string, Client> connectedClients, String data)
{
SocketAsyncEventArgs asyncEvent;
byte[] byteData = Encoding.UTF8.GetBytes(data); //It must be UTF8
lock (connectedClients)
{
foreach (Client client in connectedClients.Values)
{
try
{
asyncEvent = new SocketAsyncEventArgs();
asyncEvent.SetBuffer(byteData, 0, byteData.Length);
client.Socket.SendAsync(asyncEvent);
}
catch (Exception ex)
{
//ERROR.
}
}
}
}
But both sendToClients methods work slow for me and/or sometimes server can’t send the data to the any client. The packet can be lost.
Example:
Client1 Received 103 packets
Client2 Received 107 packets
Client3 Received 102 packets
Clientn Received 106 packets
But it should be 111 packets at the end.
Is there another methods/logics/technologies to send one data to more then one client or is there something used wrong in my examples?
Thanks in advance.
That code looks ok, but it depends on the calling code initiating the multiple send calls. Note that you can’t safely call
BeginSendmultiple times before each previous operation has finished. See here:Async Socket Writes – Potential for send operations to get mixed up? (.NET Sockets). This may explain your non-deterministic packet received counts. So if you want to go that approach, you should probably use some mechanism that prevents multiple
BeginSendcalls before previous ones have finished.But what I have been doing lately is using the new TPL and its
Task.Factory.FromAsyncmethod to convert the old APM style Begin/End X to aTask<T>:http://blogs.msdn.com/b/pfxteam/archive/2009/06/09/9716439.aspx
Once you have the Task object it is simple to schedule the next send (without overlapping the previous) by using the `Task.ContinueWith’ method.