Article View: borland.public.cppbuilder.internet.socket
Article #3033Re: Timeout Issues [Indy 9]
From: Remy Lebeau (TeamB)
Date: Fri, 25 Nov 2005 07:17
Date: Fri, 25 Nov 2005 07:17
157 lines
7147 bytes
7147 bytes
"Darlington ADIBE" <bcb@triative.com> wrote in message
news:43864c38@newsgroups.borland.com...
> when a client calls ReadLn, and a timeout occures
> what should the client (my code) do
Disconnect and reconnect. Unless you write your code to be able to recover
the communications from incomplete data without having to disconnect.
> should i clear the buffer cos when i send another command
> and calls ReadLn, it comes back with the previous reply
> which off course makes my application not to function well.
If you are not going to disconnect, then clearing the buffer is absolutely
needed. Just know that the sender will have no way of knowing that you are
doing so. And if the sender also timed out, then there may be unsent data
that will still corrupt the communication anyway.
In general, reconnecting is best, though. Keep in mind that Indy implements
its reading timeout on a per-byte basis, not a per-operation basis. For a
reading timeout to occur in between two bytes, something serious likely
happened on the socket, or the connection is very very slow, and the
connection should be reset. But that is your choice.
> AnsiString SMS = StringReplace(SMSText, "\r\n", "\r", TReplaceFlags() <<
> rfReplaceAll);
> cmd.sprintf("SENDSMS#%s#%s#", SMS, AnsiString(ToNumber));
That code should be moved inside the 'try' block. COM methods are not
allowed to let uncaught exceptions escape. Any AnsiString operation that
allocates new AnsiString values can potentially raise exceptions if there
are any memory problems.
> if( Fetch(Reply , "#") == "SENDSMS") *pVal = WideString(Reply);
That code is dangerous. You *MUST* release ownership of the BSTR that the
WideString contains. Your code is not currently doing that, so when the
WideString goes out of scope, the BSTR is automatically freed, and the code
that is calling sendSMS() will receive an invalid BSTR pointer. If you are
going to continue using WideString then you must call its Detach() method to
release ownership, ie:
if( Fetch(Reply , "#") == "SENDSMS")
*pVal = WideString(Reply).Detach(); // <-- here
> else if(tcpp->ReadLnTimedOut)
> *pVal = WideString("ERR:Remote server timedout");
> else *pVal = WideString("ERR:Unknown remote server response");
Same here as well:
else if( tcpp->ReadLnTimedOut )
*pVal = WideString("ERR:Remote server timedout").Detach();
else
*pVal = WideString("ERR:Unknown remote server response").Detach();
> *pVal = WideString("ERR:" + e.Message);
And here:
*pVal = WideString("ERR:" + e.Message).Detach();
In fact, I do not recommend that your pVal parameter be used for reporting
error messages at all. I strongly suggest that you make use of proper COM
error handling instead, which your code is not currently doing.
> return S_FALSE; /*Error(e.Message.c_str(), IID_IesemesAPI);*/
Why are you not using Error()? S_FALSE does not convey a failure, but your
exception handler did catch a failure and you are throwing away all of the
data for that failure.
I suggest you use the following code instead:
STDMETHODIMP TesemesAPIImpl::sendSMS(BSTR SMSText, BSTR ToNumber, BSTR*
pVal)
{
try
{
AnsiString SMS = StringReplace(SMSText, "\r\n", "\r",
TReplaceFlags() << rfReplaceAll);
AnsiString cmd;
cmd.sprintf("SENDSMS#%s#%s#", SMS,
AnsiString(ToNumber).c_str());
tcpp->WriteLn(cmd);
AnsiString Reply = tcpp->ReadLn(LF, IdTimeoutDefault, -1);
if( Fetch(Reply , "#") != "SENDSMS")
{
// if you decide to disconnect on timeout, then...
//
// if( tcpp->ReadLnTimedOut )
// tcpp->DisconnectSocket();
return Error(
tcpp->ReadLnTimedOut
? "Remote server timed out",
: "Unknown remote server response",
IID_IesemesAPI,
E_FAIL);
}
*pVal = WideString(Reply).Detach();
}
catch(const Exception &e)
{
return Error(e.Message.c_str(), IID_IesemesAPI, E_UNEXPECTED);
}
return S_OK;
}
Also, make sure that your TesemesAPIImpl class implements the
ISupportErrorInfo interface in order for the calling code to be able to
retreive the error data that Error() generates internally (including the
error message strings). The easiest way to do that is to add
ISupportErrorInfoImpl to your class's ancestor list:
class TesemesAPIImpl :
//...
public ISupportErrorInfoImpl<&IID_IesemesAPI>
{
//...
};
> i commented the Error(e.Message.c_str(), IID_IesemesAPI); this
> because an error msg also popup when a timeout occures.
There is nothing in the code you showed that would do that. For starters, a
reading timeout would not throw an exception in the first place, so your
exception handler would not be invoked to call Error().
> the server might have successfully executed the command, but just
> that the ACK back to the client did not arrive on time.
There is no way for the client to know if that happened. If the ACK is
lost, the client has to assume that the command was not received and
executed. The whole point of sending an ACK is for the client to know the
response to the command. Without the ACK, the command could be in limbo for
all the client knows. All the more reason to just reset the entire
connection when reading a reply to a command.
> When Error(e.Message.c_str(), IID_IesemesAPI);*/ is allowed to
> execute the client goes into unknow state
The only way that can happen is if the code that is calling sendSMS() is not
set up to handle COM errors properly in the first place.
> 2. (Mybe out off line) How best can one handle Exception in a COM
> (Automated Lib in an ActiveX Lib).
See the example above.
Gambit
Technical Details
Message-ID:
<4386ba83$1@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!newsread.com!news-xfer.newsread.com!news-out1.kabelfoon.nl!newsfeed.kabelfoon.nl!bandi.nntp.kabelfoon.nl!213.218.66.70.MISMATCH!feeder.enertel.nl!nntpfeed-01.ops.asmr-01.energis-idc.net!news-out.newsfeeds.com!propagator2-sterling.newsfeeds.com!in.nntp.be!caladan.landsraad.net!newsgroups.borland.com!not-for-mailReferences:
<43864c38@newsgroups.borland.com>Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,83a059fbd8c24375 X-Google-Attributes: gid11508e,public X-Google-Language: ENGLISH,ASCII-7-bit From: "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com> Newsgroups: borland.public.cppbuilder.internet.socket References: <43864c38@newsgroups.borland.com> Subject: Re: Timeout Issues [Indy 9] Date: Thu, 24 Nov 2005 23:17:34 -0800 Lines: 159 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1409 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1409 NNTP-Posting-Host: 68.69.17.41 Message-ID: <4386ba83$1@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1132903043 68.69.17.41 (24 Nov 2005 23:17:23 -0700) Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!newsread.com!news-xfer.newsread.com!news-out1.kabelfoon.nl!newsfeed.kabelfoon.nl!bandi.nntp.kabelfoon.nl!213.218.66.70.MISMATCH!feeder.enertel.nl!nntpfeed-01.ops.asmr-01.energis-idc.net!news-out.newsfeeds.com!propagator2-sterling.newsfeeds.com!in.nntp.be!caladan.landsraad.net!newsgroups.borland.com!not-for-mail