异步套接字的内存问题并开始发送

Posted

技术标签:

【中文标题】异步套接字的内存问题并开始发送【英文标题】:Memory Issue with async socket and begin Send 【发布时间】:2014-07-17 12:27:05 【问题描述】:

我注意到今天我正在开发的一个应用程序在内存中严重增长。 于是我做了一个Visual Studio Memory Profile,我发现了以下结果:

 Function Name  Inclusive Allocations   Exclusive Allocations   Inclusive Bytes Exclusive Bytes
 System.Net.Sockets.Socket.BeginSend(uint8[],int32,int32,valuetype System.Net.Sockets.SocketFlags,valuetype System.Net.Sockets.SocketError&,class System.AsyncCallback,object)  3 192 569   3 192 561   635 307 885 635 307 621

这是在 ~600Meg 的内存使用之上

这对我来说似乎不正确,我不知道为什么会这样?

这是我的发送功能:

private void SendSignal(Byte[] signal)
    
        if (state.WorkSocket.Connected)
        
            try
            
                state.WorkSocket.BeginSend(signal, 0, signal.Length, 0, new AsyncCallback(SendCallback), state.WorkSocket);
            
            catch (Exception e)
                                
                log.Error("Transmission Failier for ip: " + state.WorkSocket.AddressFamily , e);
            
        
        else
        
            CloseConnection();
        
    

应用程序在并发队列上阻塞要发送的消息,当它成功地将消息出列时,它会遍历所有已注册的(客户端)并将此消息发送给它们。

我是否错误地使用了开始发送?

我想到的一件事是,它是异步的,我的程序可能会遍历整个队列并将其全部卸载到异步系统缓冲区中吗?

编辑

private void SendCallback(IAsyncResult asyncResult)
    
        try
        
            Socket handler = (Socket)asyncResult.AsyncState;
            int bytesSent = handler.EndSend(asyncResult);
            if (bytesSent == 0)
            
                CloseConnection();
                return;
            
        
        catch
        
            CloseConnection();
        
    

我排空队列的方式

ExponentialBackoff eb = new ExponentialBackoff();
        while (run)
        
            //Fetch Latest Item
            ILogItem logItem;
            if (incomingQueue.TryDequeue(out logItem))
            
                //Handle the logItem
                SendEventToObservers(logItem);
                //Reset the exponetial backoff counter
                eb.reset();
            
            else
            
                //Exponential backoff thread sleep
                eb.sleep();
            
        

private void SendEventToObservers(ILogItem item)
    
        foreach (var observer in registeredObservers.ToList())
        
            if (observer != null)
            
                observer.OnMessageRecieveEvent(new ObserverEvent(item));
                // This just calls private void SendSignal(Byte[] signal)
            
        
    

【问题讨论】:

发布回调以及排空队列的方式。 @usr 完成 :) 希望对您有所帮助 【参考方案1】:

对于每个队列项,您发出一个异步发送。这意味着无限数量的发送操作可能处于未决状态。资源使用是无限的。通常,您会发出一个发送,并且仅在前一个完成后才发出下一个。

使用异步 IO,这不是那么容易做到的。要么切换到使用 await (这让它变回一个简单的问题),要么只使用同步 IO。

【讨论】:

所以我的问题是我正在将队列卸载到挂起的异步中? 是的。 ______________________________

以上是关于异步套接字的内存问题并开始发送的主要内容,如果未能解决你的问题,请参考以下文章

使用winsock发送缓冲区后可以删除内存吗?

使用异步套接字编程发送二进制数据并读取其值

Green Hills Integrity 动态内存分配

提升异步 tcp 客户端

如何使用 IOCP 发送文件?

pthread_create() 和内存泄漏