|
In a WEB application server program, it is specifically responsible for handling the browser client's request. When receiving a user's request to download a file, it calls a DLL function to the file server to obtain the requested file.
File transfer functions are implemented using Socket. There was no problem when transmitting the first file. When the second download request came, the web server called the function in the DLL.
What went wrong is in sockscore.cpp
BOOL CAsyncSocket :: AsyncSelect (long lEvent) method:
ASSERT (pState-> m_hSocketWindow! = NULL);
Checked some posts on the Internet, saying that it is a problem with multi-thread calling Socket, use Attach and Detach
To deal with. My Socket call is encapsulated in a DLL, as follows:
How can I modify it? !! !!
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 may not be useful
sockClient.Close ();
return nRet;
} |
|