// 这是per-I/O数据。它包含了在套节字上处理I/O操作的必要信息
struct CIOCPBuffer
{
WSAOVERLAPPED ol; SOCKET sClient; // AcceptEx接收的客户方套节字 char *buff; // I/O操作使用的缓冲区
int nLen; // buff缓冲区(使用的)大小 ULONG nSequenceNumber; // 此I/O的序列号 int nOperation; // 操作类型
#define OP_ACCEPT 1
#define OP_WRITE 2
#define OP_READ 3 CIOCPBuffer *pNext;
};
//------------------------------------
CIOCPBuffer *CIOCPServer::AllocateBuffer(int nLen)
{
CIOCPBuffer *pBuffer = NULL;
if(nLen > BUFFER_SIZE)
return NULL; // 为缓冲区对象申请内存
::EnterCriticalSection(&m_FreeBufferListLock);
if(m_pFreeBufferList == NULL)  // 内存池为空,申请新的内存
{
pBuffer = (CIOCPBuffer *)::HeapAlloc(GetProcessHeap(), 
HEAP_ZERO_MEMORY, sizeof(CIOCPBuffer) + BUFFER_SIZE);
}
else // 从内存池中取一块来使用
{
pBuffer = m_pFreeBufferList;
m_pFreeBufferList = m_pFreeBufferList->pNext;
pBuffer->pNext = NULL;
m_nFreeBufferCount --;
}
::LeaveCriticalSection(&m_FreeBufferListLock); // 初始化新的缓冲区对象
if(pBuffer != NULL)
{
pBuffer->buff = (char*)(pBuffer + 1);
pBuffer->nLen = nLen;
}
return pBuffer;
}真的很不明白:pBuffer->buff = (char*)(pBuffer + 1);是做什么?
请高人指点!

解决方案 »

  1.   

    所申请的内存,前一部分用于存放CIOCPBuffer的成员,后一部分才是可用的缓冲区呀
      

  2.   

    不是加1吧,应该是加上ol sClient的大小才是buff的位置
      

  3.   

    注意看这里:
    pBuffer = (CIOCPBuffer *)::HeapAlloc(GetProcessHeap(), 
    HEAP_ZERO_MEMORY, sizeof(CIOCPBuffer) + BUFFER_SIZE);,注意,不仅申请了sizeof(CIOCPBuffer,而且申请了BUFFER_SIZE。其中,pBuffer是一个CIOCPBuffer *类型的指针
    所以pBuffer指针指向的数据结构长度为sizeof(CIOCPBuffer)每次申请pBuffer这段内存的时候,最前面是CIOCPBuffer这个结构体,后面是一段buffer,大小为BUFFER_SIZE
    也就是说每次申请内存,不但申请了CIOCPBuffer,而且将申请一段长度为BUFFER_SIZE大小的bufferpBuffer+1相当于将这个指针增加了sizeof(CIOCPBuffer),(因为pBuffer指向了CIOCPBuffer,类似于long类型的指针+1等同于向后移动4字节,short类型指针+1相当于向后移动2字节)
    (char*)(pBuffer+1)指向了这段内存中超过CIOCPBuffer的部分,也就是指向了申请内存时候追加在CIOCPBuffer后面的大小为BUFFER_SIZE的那段buffer不知道这么解释,LZ理解了没有 - -#-------------------------------------------------------
    广告:VC/WinAPI 网络/多线程讨论 QQ群, 群号:41356711
      

  4.   

    个人建议结构改一下://这种常量定义建议放在最能起作用的地方,而不是与结构数据相混
    #define OP_ACCEPT 1
    #define OP_WRITE 2
    #define OP_READ 3// 这是per-I/O数据。它包含了在套节字上处理I/O操作的必要信息
    struct CIOCPBuffer
    {
    WSAOVERLAPPED ol;SOCKET sClient;// AcceptEx接收的客户方套节字/** 这里是数据指针,这个指针的作业就是为了可以很方便地指向数据区域,放后面比较合适 **/
    //char *buff;// I/O操作使用的缓冲区int nLen;// buff缓冲区(使用的)大小ULONG nSequenceNumber;// 此I/O的序列号int nOperation;// 操作类型
    CIOCPBuffer *pNext;//1.这里的buff为的是方便指向数据区别,最好是一个入口,而不是用来保存入口的指针
    //2.为了达到结构的字节对齐,方便计算结构的长度,可以使用char buff[4]
    //3.最好的办法上面部分则再放到一个完整的结构体当中,而新建一个结构体包含之前的结构体以前这个数据块(要的仅仅只是一个数据块入口位置。char buff[0];// I/O操作使用的缓冲区
    };
      

  5.   

    看清楚这里:
    pBuffer = (CIOCPBuffer *)::HeapAlloc(GetProcessHeap(), 
    HEAP_ZERO_MEMORY, sizeof(CIOCPBuffer) + BUFFER_SIZE);
    分配的空间大小是sizeof(CIOCPBuffer) + BUFFER_SIZE,
    (char*)(pBuffer+1)的意思是将指针移动sizeof(CIOCPBuffer)大小,最后指向BUFFER_SIZE缓冲区的开始位置。所以是对的。