使用TransmitFile进行内网文件传输的时候,使用多个客户端进行测试发现,服务器虚拟内存增长迅速,关闭掉所有客户端内存占用下降为2M,虚拟内存仍然很高。记录了发送的文件句柄数目和关闭的文件句柄数目,发现数目一致。程序也没有其他的地方用到虚拟内存。现在百思不得奇解。说明:并没有使用FILE_FLAG_SEQUENTIAL_SCAN

解决方案 »

  1.   

    楼主把这个方法如何使用的具体关联的Source贴出来看看。
      

  2.   


    else if(strncmp(pBuffer->pBuf+4,"0303",4)==0)//download game file
    {
      PFILE_PROPERTY pFile=(PFILE_PROPERTY)(pBuffer->pBuf+8);
    //add 0830
    char strFilePath[MAX_PATH];
    strcpy(strFilePath,pFile->FilePath);
    HANDLE hFileNew = CreateFile(
    strFilePath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 
    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL| FILE_FLAG_NO_BUFFERING, NULL);

    if (hFileNew == INVALID_HANDLE_VALUE)
    {
    LOG.LogF("CreateFile失败 文件名: %s 行号: %d 错误码: %d",__FILE__,__LINE__,GetLastError());
    return;
    }
        
    ++m_nFileHandle ;
    LOG.LogF("文件句柄数目m_nFileHandle: %d 文件名: %s 行号: %d 错误码: %d",m_nFileHandle,__FILE__,__LINE__,WSAGetLastError()); PIOCP_BUF pSendBuffer = AllocateBuffer(0);
    memset(&pSendBuffer->ol,0,sizeof(WSAOVERLAPPED));   
    pSendBuffer->sClient = pContext->s;
    pSendBuffer->hSendFile = hFileNew;

    //判断文件是否大于2G  
    pSendBuffer->i64TotalByte = ((INT64)pFile->dwFileSizeHigh << 32) + pFile->dwFileSizeLow;

    if ( pSendBuffer->i64TotalByte > 2147483648 )   //文件大于2G
    {
    //如果大于2G,则先发送2G
    pSendBuffer->i64HavedByte = 2147483647; 
    pSendBuffer->i64PerSendByte = 2147483647;
    pSendBuffer->IoOper = IOTransmitFileContinue;
    pSendBuffer->ol.OffsetHigh = 0;
    ++pSendBuffer->nOutTransmitContinue;
    if(!m_lpfntransmitfile(pSendBuffer->sClient,hFileNew,2147483647,0, &pSendBuffer->ol,NULL,TF_USE_DEFAULT_WORKER))//TF_USE_KERNEL_APC))   //不能发送2147483648
    {
    int iError = WSAGetLastError();
    if (iError != ERROR_IO_PENDING)
    LOG.LogF("m_lpfntransmitfile fail 文件大于2G 客户端Socket: %d  传输文件名: %s  文件名: %s 行号: %d 错误码: %d",pBuffer->sClient,pBuffer->pBuf+4,__FILE__,__LINE__,GetLastError());
    }
    }
    else
    {
    // 如果小于2G,则发送整个文件
    pSendBuffer->i64HavedByte = pSendBuffer->i64TotalByte;
    pSendBuffer->i64PerSendByte = pSendBuffer->i64TotalByte; 
    pSendBuffer->IoOper = IOTransmitFileCompleted;
    pSendBuffer->ol.OffsetHigh = 0;
    ++pSendBuffer->nOutTransmitCompleted;
    if(!m_lpfntransmitfile(pSendBuffer->sClient,hFileNew,0,0, &pSendBuffer->ol,NULL,TF_USE_DEFAULT_WORKER))//TF_USE_KERNEL_APC))
    {
    int iError = WSAGetLastError();
    if (iError != ERROR_IO_PENDING)
    LOG.LogF("m_lpfntransmitfile fail 文件小于2G 客户端Socket: %d  传输文件名: %s  文件名: %s 行号: %d 错误码: %d",pBuffer->sClient,pBuffer->pBuf+4,__FILE__,__LINE__,GetLastError());
    }

    }

    PostRecv(pContext,pBuffer);
    }
      

  3.   

    FILE_FLAG_NO_BUFFERING 只是添加上去试试有没有效果。这个标志原代码没有
      

  4.   

    在服务器上,默认没有限制同时进行TransmitFile的并发连接数,所以如果有多个客户端连接传输文件,会使用大量的文件cache,修改HKEY_LOCAL_MACHINE\CurrentControlSet\Services\AFD\Parameters\MaxActiveTransmitFileCount限制并发连接数试试。
      

  5.   

    现在是10个客户端不停的循环下载,控制连接数应该不是好办法呀。10个已经很少了。我开始看到FILE_FLAG_NO_BUFFERING 可以不用缓存,但加进去没有看到效果,搜索半天没有匹配TransmitFile的代码
      

  6.   

    这个标志设了有用吗?The file is being opened with no system caching. This flag does not affect hard disk caching or memory mapped files
      

  7.   

    FILE_FLAG_WRITE_THROUGHWrite operations will not go through any intermediate cache, they will go directly to disk.If FILE_FLAG_NO_BUFFERING is not also specified, so that system caching is in effect, then the data is written to the system cache, but is flushed to disk without delay.If FILE_FLAG_NO_BUFFERING is also specified, so that system caching is not in effect, then the data is immediately flushed to disk without going through the system cache. The operating system also requests a write-through the hard disk cache to persistent media. However, not all hardware supports this write-through capability.
      

  8.   

    这个不是写入操作啊,TransmitFile只是映射文件然后发送。这个标志位应该没有用
      

  9.   

    因为服务器把文件映射到内存了,所以系统使用内存就增加的很厉害。
    建议自己用文件映射,只映射一小部分,然后配合TransmitPackets,结束后重新映射下一部分。
    这样内存也能控制住,效率差多少。
      

  10.   

    看到MSDN的页面里有这么一段补充:
    On 'CreateFile' you must specify the FILE_FLAG_OVERLAPPED flagThe file must be opened using the FILE_FLAG_OVERLAPPED flag when opened with CreateFile. Else if, the file position pointer is used instead of the overlapped structure, which means that the file will be sent only on the first call. subsequent calls would send only the end of the file.楼主试试看。
    http://msdn.microsoft.com/en-us/library/ms740565(VS.85).aspx
      

  11.   

    不需要这个标志位。使用了lpOverlapped 这个参数就可以了。