如果我理解了BeginSend的逻辑:
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 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);
}
}
或者在另一方面,我可以使用SocketAsyncEventArgs发送所有客户端:
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.
}
}
}
}
但 sendToClients 方法对我来说都很慢和/或有时服务器无法将数据发送到任何客户端。数据包可能会丢失。
示例:
Client1收到103个数据包
Client2收到107个数据包
Client3收到了102个数据包
Clientn收到了106个数据包
但最后应该是111个数据包。
是否有其他方法/逻辑/技术将一个数据发送给多个客户端,或者我的示例中是否存在使用错误的内容?
提前致谢。
答案 0 :(得分:1)
该代码看起来不错,但它取决于启动多个发送调用的调用代码。请注意,在每个上一个操作完成之前,您无法安全地多次调用BeginSend
。看这里:
Async Socket Writes - Potential for send operations to get mixed up? (.NET Sockets)。这可以解释您的非确定性数据包接收计数。因此,如果你想采用这种方法,你应该使用一些机制来阻止多个BeginSend
调用,直到之前的调用完成。
但我最近一直在做的是使用新的TPL及其Task.Factory.FromAsync
方法将旧的APM样式Begin / End X转换为Task<T>
:
http://blogs.msdn.com/b/pfxteam/archive/2009/06/09/9716439.aspx
一旦有了Task对象,就可以使用`Task.ContinueWith'方法安排下一次发送(不重叠前一次)。