Solved

How to use Readbuffer on Indy's TIdTCPClient component?

Posted on 2006-07-13
15
4,729 Views
Last Modified: 2013-11-17
Hi!

void* VMes = (void*) malloc(10000);
....
TIdTCPClient* TCPConn = new TIdTCPClient(this);
...
.....
..
TCPConn->ReadBuffer(VMes,10000);

My problem is that size of the message that I recev from the server will change from message to message.
So I would like to use a size that is larger then the largest message but i cant get it to work.
When i use it this way it is stopped at TCPConn->ReadBuffer(VMes,10000) it is't a error or a exception.

The app works fine if i use static size like this

void* VMes = (void*) malloc(sizeof(*mes));
....
TIdTCPClient* TCPConn = new TIdTCPClient(this);
...
.....
..
TCPConn->ReadBuffer(VMes,sizeof(*mes));

where mes is a pointer to a structure that I am using later in the program.
Dose any one know how the readbuffer works?
The size of the mes is exactly the size that my app recv at this momemt but I have to make it flexible so that it can recv diffrent packages with diffrent sizes.
0
Comment
Question by:mikrodidakt
  • 6
  • 5
  • 4
15 Comments
 
LVL 25

Expert Comment

by:kode99
ID: 17102789
The problem is that ReadBuffer will continue to try to read until it has reached the size you specify.  So it will wait until a timeout, if any, for more data.

You can do one of two things, send the size of the message at the start of the message or use a end of line indication.

So for example you could use ReadLn which will keep reading untill it hits the specified terminator,  possibly a linefeed or carriage return.

The other approach would be to do a ReadInteger first to get the size of the incoming data and then call the ReadBuffer with the size.

0
 
LVL 16

Expert Comment

by:George Tokas
ID: 17103405
If you didn't create the component at runtime but just dropped the component at your form how you will read the buffer then??
There is a point to this question because I don't use Indy myself even though I'm registered to their comercial products.

George Tokas.
0
 
LVL 25

Expert Comment

by:kode99
ID: 17104637
Not sure I understand you question George,  you handle the TIdTCPClient the same way whether it is design time created or runtime.  Well except for having to code the settings instead of entering them into the properties.

The component maintains its own internal buffer,  the ReadBuffer only transfers the data from the components internal buffer to the buffer you pass with the ReadBuffer command.

0
 

Author Comment

by:mikrodidakt
ID: 17106265
The problem is that i have no control of the Server and the protocol.
Some idiots parden my french have writen a server that is implemented on a device and the protocol is that when a connection is established the server starts to send data. A message dose have a start tag but no end tag and the size of the message is in the middle of the message. Imight be able to use the timeout in some way because the server is sending a message in every 1-3 sec. So could i set the timeout to 1 sec?
0
 

Author Comment

by:mikrodidakt
ID: 17106268
So maybe i could set the timeout for less then 1 sec?
0
 

Author Comment

by:mikrodidakt
ID: 17106344
I would like to use TIdManagedBuffer dose any one know how to create it? I tryed following.

TIdManagedBuffer* bufferManager = new TIdManagedBuffer(this);

but apperently there should be alot more parameters and i cant find what kind of parameters.
0
 

Author Comment

by:mikrodidakt
ID: 17106389
Forget the question above.
I can get TIdManagedBuffer trough TIdTCPConnection but how do i get the TIdTCPConnection?    
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:mikrodidakt
ID: 17106451
Forget the entire question
0
 
LVL 16

Expert Comment

by:George Tokas
ID: 17107255
>>Not sure I understand you question George,  you handle the TIdTCPClient the same way whether it is design time created or runtime.

When created at design time we have allready the handler to write when a message arrive...
On the other hand on runtime creation usually we have to assign the handler after we create the component with new keyword as default handler or as overriden.
That was the meaning of my question.
As I wrote I don't use Indy myself...
But for typical TClient/TServer cases, server side, I'm using a class to deal with each client connection by assigning a TCustomWinSocket to the class and override the OnEvent method inside the class itself after the socket is assigned to the instance (Client connect).

George Tokas.
0
 
LVL 16

Expert Comment

by:George Tokas
ID: 17107376
>>The problem is that i have no control of the Server and the protocol.
Some idiots parden my french have writen a server that is implemented on a device and the protocol is that when a connection is established the server starts to send data. A message dose have a start tag but no end tag and the size of the message is in the middle of the message. Imight be able to use the timeout in some way because the server is sending a message in every 1-3 sec. So could i set the timeout to 1 sec?


Why don't you use the classic TClientSocket.
At OnRead you can read the entire buffer and there will be all the data the server sended (StartTag + data). If there is a time out before sending the next packet then there are all the data sended at that time from the server.

George Tokas.
0
 
LVL 25

Accepted Solution

by:
kode99 earned 140 total points
ID: 17110639
Too bad,  I thought maybe you had control over the server side of things also.  Would the ConnectAndGetAll work?  Does the client connect and the server just dump data and then close the connection?  If so that is easy to manage.

Another alternative could be to read the data in small chunks to look for the size message,  if there is some kind of indicator with the size you might be able to use the WaitFor command.  So your code would connect then wait for the marker with the size and then read remainder of the buffer based on that.  Also you could watch for the start marker if there are multiple items coming through the same connection.

I'm guessing you spotted the TIdConnection etc.  When working with the Indy stuff in CBuilder I find it very useful to use the hpp files as references to the classes.   The help is decent but it is missing things and some stuff is not that clear.

George,  there is no need to use handlers with TIdTCPClient.  Just do the code inline.  So you connect,  make the request, read responses etc without using any event handlers.  Because of the blocking it will proceed in order and the program will wait when needed.  That's why it works so well in a thread. TIdTCPClient is only to be used for the client side,  the TIdTCPServer is another matter.
0
 
LVL 16

Assisted Solution

by:George Tokas
George Tokas earned 110 total points
ID: 17110942
@kode99
At the next issue of bcbjournal , http://www.bcbjournal.com/index.php ,(after June's issue) there will be an article about networking Client/Server based using TClientSocket and TServerSocket.
Server side is using an instance of a class handling everything in communication by itself.
It is using the strategy I posted before.
I had bad time trying to use Indy and imagine that I'm registered to the commercial products... Maybe because I don't use Delphi... Or maybe because I'm idiot... Who knows?
Anyway I made it with standard TClient/TServer sockets without any errors and that is the reason for all my proposals here...

George Tokas.
0
 
LVL 25

Expert Comment

by:kode99
ID: 17111269
Indy's strength is the ready to go components that it has,  but it can also be a weakness.  I can put together a very functional client/server with full encryption real fast  BUT if you need to bend things to do something special it can get messy.

Largely I think that us CBuilder guys get the short end of the stick with many component's.  I have learned  Delphi over the years out of necessity and it does come in handy.  I do not think Indy has got any CBuilder examples newer than version 8,  and they are on 10 now - though I think that 10 does not fully support CBuilder yet.

I have also used the ICS package which works quite well,  nice FTP server component that works really well.
http://www.overbyte.be/frame_index.html

I look forward to the article.
0
 

Author Comment

by:mikrodidakt
ID: 17121241
Thanks for the help.
I decided to use
>>Another alternative could be to read the data in small chunks to look for the size message

the solution became following if someone should be intereseted in the future.

TCPConn->ReadBuffer(HeaderBuffer,sizeof(Header));
header = static_cast<Header*>(HeaderBuffer);
BodyBuffer  = malloc(header->MBL);
//Checking the header for errors
..
...
.....
TCPConn->ReadBuffer(BodyBuffer,header->MBL);
body  =  static_cast<S_record*>(BodyBuffer);

Some things to notice when createing the IdTCPClinet in run-time is to "#include <winsock2.h>" before windows.h. View the link.

http://carcino.gen.nz/tech/win/include_winsock2_header_file_first.php
0
 
LVL 16

Expert Comment

by:George Tokas
ID: 17121463
>>Some things to notice when createing the IdTCPClinet in run-time is to "#include <winsock2.h>" before windows.h.

The same apply on many 3rd party components...
A re-arrange of the headers usually do the work...

George Tokas.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deleti…
How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org (http://seleniumhq.org) Go to that link and select download selenium in the right hand columnThat will then direct you to their downlo…
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now