Article View: borland.public.cppbuilder.internet.socket
Article #4842Re: Detecting a client disconnect
From: paul machiaverna
Date: Thu, 25 Nov 2004 04:46
Date: Thu, 25 Nov 2004 04:46
229 lines
10277 bytes
10277 bytes
Okay, let my clarify a few things. Here is a list of the components in our
system:
1) Analyzer - A portable, handheld device that collects data that is
transmitted to a PC. The communications interface is serial IR. The serial
data flows at a rate of 19.2K bps. When a user presses the transmit key on
this analyzer, a non-protocol, binary stream of data is sent over the IR.
There is no feedback to this analyzer that the transmission succeeded or
failed. However, there is some user feedback via the Download Station
(discussed next).
2) Download Station - An IR to RS-232 converter. This is a desk/table-top
piece of equipment. The Analyzer is placed into this converter and data
transmissions are performed. There is a tri-colored LED and a piezo
transducer for user feedback. The Download Station defaults to receiving IR
data and sending it over the RS-232 port. Data received from the RS-232
port is passed through a state machine and not to the IR port. This allows
the following sequence:
- The Analyzer "BEGIN" is received by the Indy based application on the
Remote PC server.
- The Indy based application sends a control byte to the Download Station
to make the LED blink and have the piezo
transducer click. This indicates to the user that a communications
link has been established.
- When the Indy based applcation receives the "END" from the analyzer, an
integrity check is performed on the data
(checksum verification). If the integrity check passes, a command
byte is sent to the Download Station to "good
beep". If it fails, a "bad beep".
3) Device Server - A RS-232 to TCP/IP over Ethernet converter. The Download
Stations are connected to these. The remote PC server IP address and TCP
port (on which the INDY TIdTcpServer is listening) is programmed into the
Device Server. From the perspective of the INDY application, these are the
clients. Whenever data is present on the RS-232 port, a connection is made
to the remote PC. After 30 seconds of inactivity, these clients disconnect.
4) Remote PC Server - Runs an application using INDY for network
communications.
When I wrote "...changing over to a different scheme is going to be quite a
bit of work" I wasn't talking about changing the Analyzer protocol. The
fact is that there is no changing this method of communications. The
Analyzer is a legacy product that must be supported. A lack of resources
(memory and CPU power) in it does not allow us to add a communications
protocol. I was referring to changing the scheme of how Indy is used in the
PC server application. Of course, through your examples and suggestions I
can see that there are clear advantages to doing the network communications
the true Indy way.
Have a Happy Thanksgiving and I'll be checking here from time to time over
the holiday weekend.
Paul Mac
"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:41a50da0$1@newsgroups.borland.com...
>
> "Paul Machiaverna" <paul.machiaverna@i-stat.com> wrote in message
> news:41a4fb02$1@newsgroups.borland.com...
>
> > The network communuication code in the application is from the
> > days from WinShoes with minor modifications to work with Indy.
>
> WinShoes is a very different library from Indy. You really need to update
> to true Indy logic, not WnShoe-adapted logic.
>
> > One example is a device that communicates binary data at 19.2 Kbps with
> > NO protocol. It's a raw data dump. This data varies in size, but
always
> starts
> > and ends with known strings, "BEGIN" and "END". The device servers
> packetize
> > this data at whatever algorithm they choose. A connection to the server
> (INDY
> > application) whenever data is detected on the serial port.
>
> Ok, now you are confusing me about who is who in this situation. Please
use
> more descriptive names then "device" and "server". Your description
> suggestions the "device" is the "Server" is that right? Why is the data
not
> using any protocol? Even a raw dump send by the TIdTCPServer should use
> some protocol to help the client manage the data reading easier. You
could
> use a protocol like this:
>
> void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
> {
> if( first time )
> {
> AThread->Connection->WriteInteger(5);
> AThread->Connection->Write("BEGIN");
> first time = false;
> }
>
> // read data from serial port as needed
> if( data available )
> {
> AThread->Connection->WriteInteger(size of raw data);
> AThread->Connection->WriteBuffer(raw data, size of raw data);
> }
>
> if( no more data available )
> {
> AThread->Connection->WriteInteger(3);
> AThread->Connection->Write("END");
> }
> }
>
> That way, the client can read an integer first, which tells how many
> remaining bytes to read for that particular packet. If the packet data is
> "BEGIN" then start processing future raw data. If the packet data is
"END"
> then stop processing future raw data. Everything else is raw data.
>
> bool processraw = false;
> while( connected )
> {
> read an integer
> read specified number of bytes
>
> if( bytes are "BEGIN" )
> processraw = true;
>
> else if( bytes are "END" )
> processraw = false;
>
> else if( processraw )
> process bytes as needed
> }
>
> So you see, even with a small protocol, you still preserve your raw dump
> while providing easier reading. No more buffering every single byte. No
> more state machines.
>
> > From the server perspective, a client connects and data is read from
> > the socket. Then this data is transferred to a receive buffer that is
> large
> > enough to hold the entire (maximum) number of bytes.
>
> That does not sound like a very good design to me. Especially since Indy
> already maintains its own receive buffer anyway. You don't need your own
> buffering.
>
> > As data is transferred to this buffer each byte is fed through a state
> machine.
> > This detects the "BEGIN" and "END", which are triggers for sending meta
> data back towards the device.
>
> So, are you saing that the "device" is actually the client and the
> TIdTCPServer will be receiving the "BEGIN and "END" strings rather than
> issuing them to the client? If that is the case, then the situation is
> still easy to manage:
>
> void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
> {
> if( AThread->Connection->ReadFromStack(true, 125) != -1 )
> {
> int index;
>
> if( firsttime )
> {
> index = find index of "BEGIN" in
> AThread->Connection->InputBuffer;
> if( index == -1 )
> return;
>
> AThread->Connection->InputBuffer->Remove(index+5);
> first time = false;
> }
>
> index = find index of "END" in
AThread->Connection->InputBuffer;
> if( index == -1 )
> return;
>
> // process AThread->Connection->InputBuffer->Memory
> // up to index number of bytes as needed...
>
> AThread->Connection->InputBuffer->Remove(index+3);
> first time = true;
> }
>
> if( data needs to be transmitted )
> AThread->Connection->WriteBuffer(data to send, size of data to
> send);
> }
>
> > There is yet another layer of complexity to this. When the "END" is
> received,
> > data processing is performed and there are some situations where a
> secondary
> > transmission session is started by the server to update parameters in
the
> device.
> > This transmission is protocol driven using an implementation of ASTM.
>
> Indy works very well with protocols.
>
> > We all that said, changing over to a different scheme is going to be
quite
> a bit
> > of work. Note that the above scheme has been working very well
(extremely
> > stable) for over 5 years. All I'm trying to add is the ability to
detect
> a client
> > disconnect reliably.
>
> To do that, you first need to use Indy the way it was designed to be used.
> That means NOT calling Readable() and Recv() directly. Use the reading
> methods of TIdTCPConnection instead of TIdSocketHandle directly.
> TIdTCPConnection performs all of the necessary error handling and such to
> detect and report disconnects.
>
> > Supporting the old transmissions is a pain at best in these days of
> packetized
> > protocols. We (my company) had called in a few different consultants to
> talk
> > about how to support our legacy devices in network communications.
>
> I just described above how you can do it.
>
>
> Gambit
>
>
Technical Details
Message-ID:
<41a563c6@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!proxad.net!213.200.89.82.MISMATCH!tiscali!newsfeed1.ip.tiscali.net!border2.nntp.ams.giganews.com!nntp.giganews.com!pe2.news.blueyonder.co.uk!blueyonder!news-peer-test!btnet!newsfeed.bt.es!caladan.landsraad.net!newsgroups.borland.com!not-for-mailReferences:
<41a3a222$1@newsgroups.borland.com> <41a3a429@newsgroups.borland.com> <41a4aed9$3@newsgroups.borland.com> <41a4d9d0$1@newsgroups.borland.com> <41a4e2b4$1@newsgroups.borland.com> <41a4f0e2@newsgroups.borland.com> <41a4fb02$1@newsgroups.borland.com> <41a50da0$1@newsgroups.borland.com>Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,2bbc0c2eefeb0788 X-Google-Attributes: gid11508e,public X-Google-Language: ENGLISH,ASCII-7-bit From: "paul machiaverna" <machiaverna@verizon.net> Newsgroups: borland.public.cppbuilder.internet.socket References: <41a3a222$1@newsgroups.borland.com> <41a3a429@newsgroups.borland.com> <41a4aed9$3@newsgroups.borland.com> <41a4d9d0$1@newsgroups.borland.com> <41a4e2b4$1@newsgroups.borland.com> <41a4f0e2@newsgroups.borland.com> <41a4fb02$1@newsgroups.borland.com> <41a50da0$1@newsgroups.borland.com> Subject: Re: Detecting a client disconnect Date: Wed, 24 Nov 2004 23:46:53 -0500 Lines: 231 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2800.1437 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441 NNTP-Posting-Host: 68.239.169.59 Message-ID: <41a563c6@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1101358022 68.239.169.59 (24 Nov 2004 20:47:02 -0700) Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!proxad.net!213.200.89.82.MISMATCH!tiscali!newsfeed1.ip.tiscali.net!border2.nntp.ams.giganews.com!nntp.giganews.com!pe2.news.blueyonder.co.uk!blueyonder!news-peer-test!btnet!newsfeed.bt.es!caladan.landsraad.net!newsgroups.borland.com!not-for-mail