关于C#高性能Socket服务器SocketAsyncEventArgs的实现的一些疑问

Tyrael_Tian 2016-09-03 01:32:30
// This class creates a single large buffer which can be divided up
// and assigned to SocketAsyncEventArgs objects for use with each
// socket I/O operation.

// This enables bufffers to be easily reused and guards against
// fragmenting heap memory.
//
// The operations exposed on the BufferManager class are not thread safe.
class BufferManager
{
int m_numBytes; // the total number of bytes controlled by the buffer pool
byte[] m_buffer; // the underlying byte array maintained by the Buffer Manager
Stack m_freeIndexPool; //
int m_currentIndex;
int m_bufferSize;
public BufferManager(int totalBytes, int bufferSize)
{
m_numBytes = totalBytes;
m_currentIndex = 0;
m_bufferSize = bufferSize;
m_freeIndexPool = new Stack<int>();
}

// Allocates buffer space used by the buffer pool
public void InitBuffer()
{
// create one big large buffer and divide that
// out to each SocketAsyncEventArg object
m_buffer = new byte[m_numBytes];
}

// Assigns a buffer from the buffer pool to the
// specified SocketAsyncEventArgs object
//
// <returns>true if the buffer was successfully set, else false</returns>
public bool SetBuffer(SocketAsyncEventArgs args)
{

if (m_freeIndexPool.Count > 0)
{
args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize);
}
else
{
if ((m_numBytes - m_bufferSize) < m_currentIndex)
{
return false;
}
args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize);
m_currentIndex += m_bufferSize;
}
return true;
}

// Removes the buffer from a SocketAsyncEventArg object.
// This frees the buffer back to the buffer pool
public void FreeBuffer(SocketAsyncEventArgs args)
{
m_freeIndexPool.Push(args.Offset);
args.SetBuffer(null, 0, 0);
}
}
上面是MSDN官网给出的案例,在BufferManager类中有一个变量是 m_freeIndexPool,我看了很久这一段代码始终搞不明白这个变量存储的int集合代表的是什么意义,并且为什么在SetBuffer(SocketAsyncEventArgs args)方法中,m_freeIndexPool.Count > 0 就可以把接收到的数据放入m_buffer中?
MSDN官网上BufferManager类的地址:https://msdn.microsoft.com/zh-cn/library/bb517542.aspx
...全文
258 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Tyrael_Tian 2016-09-08
  • 打赏
  • 举报
回复
引用 3 楼 CGabriel 的回复:
是避免内存碎片的一种方法。 预先申请一块很大的内存,然后平均分成若干各小块, index 实际就是每个小块的编号。 用的时候根据编号直接找到小块内存,直接覆写就是。这样就不用每次都重新分配内存了。 可以理解为先买一层巨大的,空旷的楼层。然后切成一个一个小单元
大大,您好, public bool SetBuffer(SocketAsyncEventArgs args) { if (m_freeIndexPool.Count > 0) { args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize); } else { if ((m_numBytes - m_bufferSize) < m_currentIndex) { return false; } args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize); m_currentIndex += m_bufferSize; } return true; } 这个方法中的 if-else 我也没有看懂, 如果说,if里面的判断 m_freeIndexPool.Count > 0 说明的是 byte[] m_buffer 这里面有空间,所以可以往 m_buffer 塞东西进去, 但是,else 的判断是m_freeIndexPool.Count <= 0 这里我就看不懂了,既然m_freeIndexPool.Count <= 0 说明 m_buffer 就已经装满了,为什么不直接 return false, 不就行了吗? 为什么 还要先做 if ((m_numBytes - m_bufferSize) < m_currentIndex) 这个判断才 return false,还有后面为什么 args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize); 这里还可以往 m_buffer 里面塞东西,这个else 不是表达就是 m_freeIndexPool.Count <= 0 ,说明 m_buffer 装满了吗? 这里我始终没搞明白。
Tyrael_Tian 2016-09-08
  • 打赏
  • 举报
回复
引用 3 楼 CGabriel 的回复:
是避免内存碎片的一种方法。 预先申请一块很大的内存,然后平均分成若干各小块, index 实际就是每个小块的编号。 用的时候根据编号直接找到小块内存,直接覆写就是。这样就不用每次都重新分配内存了。 可以理解为先买一层巨大的,空旷的楼层。然后切成一个一个小单元
还想请教一下,最后那个方法, public void FreeBuffer(SocketAsyncEventArgs args) { m_freeIndexPool.Push(args.Offset); args.SetBuffer(null, 0, 0); } 为什么args.SetBuffer(null, 0, 0); 括号里面是 (null, 0, 0)? 这里第一个参数是null,我始终想不通是为什么。 第一个传的不应该是byte[] 吗?
Tyrael_Tian 2016-09-08
  • 打赏
  • 举报
回复
引用 3 楼 CGabriel 的回复:
是避免内存碎片的一种方法。 预先申请一块很大的内存,然后平均分成若干各小块, index 实际就是每个小块的编号。 用的时候根据编号直接找到小块内存,直接覆写就是。这样就不用每次都重新分配内存了。 可以理解为先买一层巨大的,空旷的楼层。然后切成一个一个小单元
谢谢,楼房的举例很生动。
CGabriel 2016-09-05
  • 打赏
  • 举报
回复
是避免内存碎片的一种方法。 预先申请一块很大的内存,然后平均分成若干各小块, index 实际就是每个小块的编号。 用的时候根据编号直接找到小块内存,直接覆写就是。这样就不用每次都重新分配内存了。 可以理解为先买一层巨大的,空旷的楼层。然后切成一个一个小单元
Poopaye 2016-09-03
  • 打赏
  • 举报
回复
开头的注释已经说的很完整了啊 // This class creates a single large buffer which can be divided up // and assigned to SocketAsyncEventArgs objects for use with each // socket I/O operation. // This enables bufffers to be easily reused and guards against // fragmenting heap memory. 就是先创建一个很大的byte[],然后把它分割成好几份,传递给SocketAsyncEventArgs使用 那个stack就是记录分割的位置,每次要用的时候取一个出来,用完放回去
Tyrael_Tian 2016-09-03
  • 打赏
  • 举报
回复
m_freeIndexPool在声明的时候是:Stack<int> m_freeIndexPool; 上面漏写了,不好意思,希望大牛们,帮忙解答一下。

110,502

社区成员

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

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

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