最近把一个接收socket服务端软件升级为iocp方案,其实就是换成c#的socket的异步方法,主要参考的是微软写的Server类,然后再百度找到基于这个类实现的代码来改造
上线一两天后,软件崩溃了,查日志发现报了很多OutOfMemoryExceptions错误,都是在发送方法上。
因为我发送方法用的SocketAsyncEventArgs是自己new的,不是从SocketAsyncEventArgsPool池里分配的,所以发送后一直没被GC回收掉。
短短5分钟,就占用了1.5G
我发送的方法是这样的,微软它的的例子就没这个问题,因为它每个socket接收跟发送都是用的同一个SocketAsyncEventArgs。它是收包后,再发包,然后再收包,这个SocketAsyncEventArgs一直贯穿于里面,但实际场景根本没法跟微软那例子一样,我可能要主动发包给客户端,或者客户端发包给我,我不需要回包给客户,或者客户端发了粘包给我,我需要拆分开发两个包给客户端。所以我接收都是用的同一个SocketAsyncEventArgs,但发送是另外new的。
public void SendBytes(AsyncUserToken userToken, byte[] bytes) { if (userToken == null || userToken.Socket == null || !userToken.Socket.Connected) return; try { //新建异步发送对象, 发送消息 SocketAsyncEventArgs sendArg = new SocketAsyncEventArgs(); sendArg.UserToken = userToken; sendArg.SetBuffer(bytes, 0, bytes.Length); //将数据放置进去. userToken.Socket.SendAsync(sendArg); } catch (Exception e) { UIManager.LogException(e); } }
我后面也想过也在SocketAsyncEventArgsPool池里面分配,但它这个SetBuffer方法不太懂怎么用,我不知怎么把我的数据传进去,如果SetBuffer(bytes,0,bytes.Length),那它不就引用到我这个字节上,跟bufferManager的缓存数组没引用关系了。也还是会占用内存。
后面查资料时发现这一段话,具体链接 https://www.coder.work/article/1593333
似乎它这个异步SendAsync本身性能就不是很好,我就用回同步的发包方法Send,改回后就非常稳定了
标签:OutOfMemoryExceptions,SocketAsyncEventArgs,bytes,sendArg,发送,发包,内存,userToken From: https://www.cnblogs.com/caijt/p/17632715.html