求助:C# socket异步通信,大量消息卡在SendAsync之后,回调方法之前

chen_ya_ping 2013-05-24 01:16:13
模拟450个用户移动,发送移动消息,实际不到450人的时候,服务端发送消息已经卡的比较厉害了,具体表现为消息已经调用SendAsync方法,但是没有触发回调。所以SocketAsyncEventArgs对象已经消息体都驻留在内存中,导致内存不断变大。
发送以及统计部分代码:
Interlocked.Increment(ref totalCount); //总计发送消息数量 +1
Interlocked.Increment(ref currentCount);//等待发送消息 +1
bool willRaiseEvent = _acceptedSocket.SendAsync(sendEventArgs);
if (!willRaiseEvent){
ProcessSend(sendEventArgs);
}
回调部分代码方法:
private void ProcessSend(SocketAsyncEventArgs e){
try{
Interlocked.Decrement(ref currentCount);//发送成功后 -1
var bufferLength = (int) (e.UserToken);
int count = e.BytesTransferred;
SocketError error = e.SocketError;
if (error != SocketError.Success){
//string ip = RemoteEndPoint.ToString();
//Log.Error(string.Format("发送消息异常,SocketError:{0},远程地址:{1}", error, ip));
_segementBufferManager.FreeBufferListAndEventArgs(e, SendEventArgsCompleted);
SafeCloseSocket();
FireConnectionErrorAsync(new SocketException((int) (error)), TcpConnectionErrorType.EndSend);
return;
}
统计消息有一个timer每300毫秒打印一次,该部分代码:
int nWorkThreads, nIOThreads;
ThreadPool.GetAvailableThreads(out nWorkThreads, out nIOThreads);
LogWriter.Error(Guid.Empty, 2, string.Format("消息总计:{0},等待发送:{1},空闲工作线程:{2},空闲io线程:{3}", TcpConnection.totalCount, TcpConnection.currentCount, nWorkThreads, nIOThreads));

模拟450个用户移动,发送移动消息,实际不到450的时候,服务端发送消息已经卡的比较厉害了。
实际测试的结果:
[2013-05-24 13:09:48,290]消息总计:14241,等待发送:5273,可用工作线程:32765,可用io线程:1000
[2013-05-24 13:09:48,602]消息总计:14331,等待发送:5327,可用工作线程:32766,可用io线程:1000
[2013-05-24 13:09:48,915]消息总计:14344,等待发送:5335,可用工作线程:32766,可用io线程:1000
网络带宽:10Gbps,毫无压力;cpu 毫无压力,内存因为消息积压,会不断增长。
...全文
1393 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
qingruibin 2013-09-25
  • 打赏
  • 举报
回复
我也是遇到了同样的问题 而且用完之后 貌似内存好一段时间还是在的
chen_ya_ping 2013-05-24
  • 打赏
  • 举报
回复
恩,发送的时候已经考虑了消息的大小了,不会大于4k的,socket系统默认的发送缓冲区是8k,多次试验,发现一般是发送消息达到每秒300个左右时,就开始出现这种现象了,但是socket的通信处理消息的能力应该远高于这个数据的。
Mirror然 2013-05-24
  • 打赏
  • 举报
回复
SocketAsyncEventArgs在发送数据时比较难以驾驭,在发送未完成时,如果继续调用它,则引发异常,在实现SocketAsync时,如果发送的数据大于发送缓冲区,需要把数据拆开,发送第一小包完之后,才可以发送第二个小包,依此类推。 参考MSDN把
chen_ya_ping 2013-05-24
  • 打赏
  • 举报
回复
消息放入队列,然后开启固定数量线程发送的方式我也试过了,跟现在的情况一样。并发量也不大,实际链接人数不到450已经出现这个问题,发送消息总量的也不大,也就总计才发送1w多条,而且,我450个链接是采用1秒钟连接一个的方式逐步链接上的;现在最主要的是问题是消息卡在调用了SendAsync方法之后,到触发回调之前,所以客户端看到的消息就延迟比较严重,比如看到的实际上是5秒或者更久之前的消息。
viki117 2013-05-24
  • 打赏
  • 举报
回复
你不要再处理消息,只是单纯的把回传的数据丢一个队列里保存起来,如果没问题,就说明是你处理代码的问题,如果有问题,那就说明socket本身有问题; 另外就是大量socket连接下,控制下并发量,把要发送的信息和socket对象放入队列,去while这个队列,就算卡死或者队列过长,也不能让程序崩了
chen_ya_ping 2013-05-24
  • 打赏
  • 举报
回复
现在不是并发的问题,消息数量并不多,你看日志占用的工作线程最多时才2个,io线程一个都没有占用。我搞不明白的是,调用了SendAsync方法之后,到触发回调,这段时间,按道理,系统只是把SocketAsyncEventArgs对象中的数据拷贝到Socket的SendBuffer缓冲区中而已,如果说这个缓冲区已满,但是这个好的网络,为什么这么一点点消息都来不及发送呢?
qldsrx 2013-05-24
  • 打赏
  • 举报
回复
控制线程数量,控制并发数量,即使有450个并发,你也要想办法让他们进行排队,设置10个队列应该足够了。

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧