在一个WEB应用服务器程序里,专门负责处理Browser客户端的请求,当接收到用户下载文件的请求后,调用一个DLL的函数去文件服务器获取所请求的文件。
文件传输的函数是用Socket实现的。在传第一个文件的时候没问题,当第二个下载请求到来后,WEB服务器调DLL里的函数出错了,出错的地方在sockcore.cpp
的BOOL CAsyncSocket::AsyncSelect(long lEvent)方法:ASSERT(pState->m_hSocketWindow != NULL);查了网上一些帖子,说是多线程调用Socket出的问题,要使用Attach和Detach
来处理。我的Socket调用是封装在一个DLL里的,如下:请问该如何修改?!!int getRemoteFile(CString strIP, CString fName,int port)
{ int nRet = 0; // return value AfxSocketInit(NULL);//should comment this line? CSocket sockClient;
sockClient.Create(); sockClient.Connect( strIP, port); int dataLength, cbBytesRet, cbLeftToReceive;
// pointer to buffer for receiving data
// (memory is allocated after obtaining file size)
BYTE* recdData = NULL;
    
CFile destFile;
CFileException fe;
BOOL bFileIsOpen = FALSE;
    
// open/create target file that receives the transferred data
    
if( !( bFileIsOpen = destFile.Open( fName, CFile::modeCreate | 
CFile::modeWrite | CFile::typeBinary, &fe ) ) )
{
TCHAR strCause[256];
fe.GetErrorMessage( strCause, 255 );
TRACE( "GetFileFromRemoteSender encountered an error ");
//AfxMessageBox(strCause);
/* you should handle the error here */
        
nRet = -1;
goto PreReturnCleanup;
}
    
// get the file's size first
cbLeftToReceive = sizeof( dataLength );
do
{
BYTE* bp = (BYTE*)(&dataLength) + sizeof(dataLength) - cbLeftToReceive;
cbBytesRet = sockClient.Receive( bp, cbLeftToReceive );
        
// test for errors and get out if they occurred
if ( cbBytesRet == SOCKET_ERROR || cbBytesRet == 0 )
{
int iErr = ::GetLastError();
//TRACE( "GetFileFromRemoteSite returned a socket error");
/* you should handle the error here */
            
nRet = -2;
goto PreReturnCleanup;
}
        
// good data was retrieved, so accumulate
// it with already-received data
cbLeftToReceive -= cbBytesRet;
}
while ( cbLeftToReceive > 0 ); dataLength = ntohl( dataLength ); // now get the file in RECV_BUFFER_SIZE chunks at a time
    
recdData = new byte[RECV_BUFFER_SIZE];
cbLeftToReceive = dataLength;
    
do
{    
int iiGet, iiRecd; iiGet = (cbLeftToReceive<RECV_BUFFER_SIZE) ? 
                      cbLeftToReceive : RECV_BUFFER_SIZE ;
iiRecd = sockClient.Receive( recdData, iiGet ); // test for errors and get out if they occurred
if ( iiRecd == SOCKET_ERROR || iiRecd == 0 )
{
    int iErr = ::GetLastError();
    //TRACE( "returned a socket error");
    CString errMsg;
    errMsg.Format("%d",iErr);
    /* you should handle the error here */
            
    nRet = -3;
    goto PreReturnCleanup;
} destFile.Write( recdData, iiRecd); // Write it
cbLeftToReceive -= iiRecd; } 
while ( cbLeftToReceive > 0 );PreReturnCleanup: // labelled "goto" destination delete[] recdData;        
    
if ( bFileIsOpen )
destFile.Close();
// only close file if it's open (open might have failed above)
sockClient.Detach();//detach 或许没用
sockClient.Close();    return nRet;
}

解决方案 »

  1.   

    在函数头加上
    AfxManageModuleState
      

  2.   

    CAsyncSocket和CSocket需要一个窗口对象做消息处理,因此你需要自己创建一个CWnd对象。具体过程你可以查一下以前的帖子,有人问过并解决了。
    其实这两个类并不好用,建议你使用Winsock2的API。
      

  3.   

    to:jeffchen(Jeff) 酱紫啊,可是这个DLL我是给java调用滴(就是通过JNI),所以..
    好像创建CWnd对象有难度....
    用Winsock2的API怎么搞捏?麻烦给段代码示例
      

  4.   

    Socket API? 可以阅读《Windows网络编程》
      

  5.   

    CAsyncSocket和CSocket不是线程安全的
      

  6.   

    创建一个不可见的窗口即可,因为只是用它做消息处理。
    to ouyh12345() :
    CAsyncSocket和CSocket的线程安全是通过CWnd做消息处理实现的。
      

  7.   

    我以前也遇到过类似问题,使用CAsyncSocket和CSocket类都会出异常,最后还是用winsock套接字的api解决的问题.