在一个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;
}
文件传输的函数是用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;
}
AfxManageModuleState
其实这两个类并不好用,建议你使用Winsock2的API。
好像创建CWnd对象有难度....
用Winsock2的API怎么搞捏?麻烦给段代码示例
to ouyh12345() :
CAsyncSocket和CSocket的线程安全是通过CWnd做消息处理实现的。