Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How to use Readbuffer on Indy's TIdTCPClient component?

Posted on 2006-07-13
15
Medium Priority
?
5,049 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

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
 

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 560 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 440 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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In our object-oriented world the class is a minimal unit, a brick for constructing our applications. It is an abstraction and we know well how to use it. In well-designed software we are not usually interested in knowing how objects look in memory. …
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…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.

715 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