-
CSocket MFC Problem
We have a client server implementation using a CSocket derived class, a CSocketFile and two archives ( one for receiving, one for sending ) in the connection class. So far it seems to be pretty vanilla and right out of the book.
However, I get error messages while sending from the server to the client once in a while, totally unpredictable and not reproducable. The message itself is not spectacular. It says, roughly translated: "unknown error accessing an unknown file". The unknown file is the socket, so it basically says "sending failed".
PHP Code:
BOOL CSAZConnection::Send( const CSAZMessage* SazMsg )
{
LOG_ENTER( CSAZConnection::Send );
CSingleLock SingleLock( &m_SendMutex );
SingleLock.Lock();
if( ! IsOpen() )
{
LOG_DUMP( "Connection is not open" )
LOG_EXIT( CSAZConnection::Send );
return FALSE;
}
if( GetError() )
{
LOG_DUMP( "Connection had errors" )
LOG_EXIT( CSAZConnection::Send );
return FALSE;
}
LOG_DUMP_NUMERIC( SazMsg->mv_MessageType )
//
// Falls kein Socket existiert, kann keine Nachricht versandt werden
//
if( m_pSocket == NULL )
{
LOG_DUMP( "Socket is NULL" )
LOG_EXIT( CSAZConnection::Send );
return FALSE;
}
//
// Falls der Socket blockiert ist hier abbrechen
//
if( TimedOutWhileBlocking() )
{
LOG_EXIT( CSAZConnection::Send );
return FALSE;
}
//
// Jetzt die Nachricht senden und den
// temporären Buffer leeren
//
try
{
LOG_DUMP( "trying to stream into archive" )
(*m_pArchiveOut) << (*SazMsg);
LOG_DUMP( "flushing archive" )
m_pArchiveOut->Flush();
LOG_DUMP( "flushing done" )
OutputDebugString( "Message sent" );
//LOG_DUMP( SazMsg->ToDebugString() );
}
catch( CException *e )
{
SendErrorMessage( e,
_T("Error while sending Message [Type:[%u], Action:[%u]]: "),
SazMsg->mv_MessageType,
SazMsg->mv_Action );
LOG_EXIT( CSAZConnection::Send );
return FALSE;
}
catch(...)
{
SendErrorMessage( NULL,
_T("Error while sending Message [Type:[%u], Action:[%u]]: Unknown"),
SazMsg->mv_MessageType,
SazMsg->mv_Action );
LOG_EXIT( CSAZConnection::Send );
return FALSE;
}
//
// Sendung erfolgreich
//
LOG_EXIT( CSAZConnection::Send );
return TRUE;
}
This function produces the following log:
Code:
12/09/04 13:56:37 (0960DFA0) Enter: CSAZConnection::Send
12/09/04 13:56:37 (0960DFA0) 2010
12/09/04 13:56:37 (0960DFA0) Enter: CSAZConnection::TimedOutWhileBlocking
12/09/04 13:56:37 (0960DFA0) Exit: CSAZConnection::TimedOutWhileBlocking
12/09/04 13:56:37 (0960DFA0) trying to stream into archive
12/09/04 13:56:37 (0960DFA0) flushing archive
12/09/04 13:58:19 (0960DFA0) Enter: CSAZConnection::SendErrorMessage
12/09/04 13:58:19 (0960DFA0) Enter: CSAZConnection::SetError
12/09/04 13:58:19 (0960DFA0) Exit: CSAZConnection::SetError
12/09/04 13:58:19 (0960DFA0) Exit: CSAZConnection::SendErrorMessage
12/09/04 13:58:19 (0960DFA0) Exit: CSAZConnection::Send
Note the lines
->> LOG_DUMP( "trying to stream into archive" )
->> LOG_DUMP( "flushing archive" )
and the absence of
->> LOG_DUMP( "flushing done" )
plus the fact that the exception thrown explicitly states that an error occurred in the socket.
I'm stumped. I'd say that it's not in my hands anymore and it's a network i.e. Hardware error, but no other programms we use have problems ( or rather they have, but my boss doesn't want to see them ).
So is there anything I can do about this safe of writing my own winsock wrapper ( and have that fail if it's a network problem ) ?
I have found a lot of sites advising against using CSocket, but I have not yet heard a single fact why and what to use instead.
-
I've never used CSocket so I don't know exactly what's wrong. Shouldn't you be able to to find a more specific error explanation somewhere? In the case of an error CSocketFile::Write calls AfxThrowFileException(CFileException::generic, nError), nerror being the return code from m_pSocket->GetLastError(), the last winapi operation that failed. So, while the cause of the exception is generic, you can retrieve the IOsError, for which if I'm correct could be looked up in winapi error code charts.
-
That sounds good, I'll check it on monday.
-
Good idea, I implemented it. As I cannot reproduce the error, I cannot check. The new production version will "ship" ( be installed on our own servers ) on wednesday, so I might be back with additional information some time after that :rolleyes:
-
PHP Code:
try
{
m_pSocket->SetTimeOut();
LOG_DUMP( "trying to stream into archive" )
(*m_pArchiveOut) << (*SazMsg);
LOG_DUMP( "flushing archive" )
m_pArchiveOut->Flush();
LOG_DUMP( "flushing done" )
m_pSocket->KillTimeOut();
}
catch( CFileException *f )
{
LPVOID lpMsgBuf = NULL;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
f->m_lOsError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL );
SendErrorMessage( f,
_T("Error while sending ( GetLastError returned %d = '%s' ) Message [Type:[%u], Action:[%u]]: "),
f->m_lOsError,
lpMsgBuf,
SazMsg->mv_MessageType,
SazMsg->mv_Action );
LocalFree( lpMsgBuf );
}
So I added the additional catch block and waited for an error to happen. Maybe I made a silly mistake, but it returned the following:
[code]
Error while sending ( GetLastError returned 1241096 = '‹uÀj' ) Message [Type:[159015328], Action:[1242880]]: ( Exception Message: Ein unbekannter Fehler ist beim Zugriff auf eine unbenannte Datei aufgetreten. )
[/quote]
which is total gibberish and not a valid error code ( 0-15000 ) either.
Note that the flushing took 25 Minutes (!!!) until it threw an exception. As the program itself has only a single thread, there are no threading issues involved from my side. The connection did not do anything else on another thread from the socket either. It just stood there for 25 Minutes, not refreshing, waiting...
-
By adjusting some of the options for the Debug->Exception dialog you can set a break point for the exception thrown. Then, when your code gets an exception, it should break somewhere in the mfc source code.
-
That sounds good, but I cannot reproduce this exception. So I have to sit and wait until it occurs on our production systems where we cannot employ debug versions. I will have to rely on log files :(
A colleague is building another application using our connection so we have an automated testing environment ready for debugging in a few days.
-
To throw a FileException an IOsError value has to be passed in, the default value being -1. I think either MS has forgot to initialize a variable somewhere, or there's some yet unknown error code, or you have stack overflow that jumps to the exception. But if you can reproduce the error on the debug build, you should be able to tell which one.
-
RE:CSocket MFC Problem:nvoigt. [QUOTE]I have exactly the same problem and would like to know the if a solution was found.
-
Bringing up old threads is against the forum rules. I'll just give a short info about what happened in this case. As it will be quite unhelpful, please open up a new thread ( maybe including a link to this thread ) with your specific problem.
I was reading all over the net that CSocket was not reliable and you should write your own socket class. I could never find a reason why, it all seemed to be posts by good, but misinformed coders. I implemented my own socket class which worked better and was easier to work with than CSocket. I can only recommend that step not as a solution, but as a coding excercise to learn from. I did.
As our network is known ( which means "is known to everyone but my boss who doesn't want to see something is wrong that might cost money" ) to be the troublemaker with many applications including our database, Office software and finally our own product, we implemented our own Socket class that uses RUDP ( reliable UDP, which basically is UDP with packet loss checking and resending on top ). We still have the problems with the network, seeing other applications crash and burn is really no big thing, happens daily. But our servers are running fine, because we use a fault tolerant protocol where we need it.
I'm not sure this is the solution you're looking for, so feel free to open up a new thread going into detail about your problem.