Code examples for CPPB 2010?

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Code examples for CPPB 2010?

Postby mknoblock » Fri Nov 06, 2009 1:41 pm

I'm an old,old user of C++ Builder 5, and need to upgrade to RAD Studio 2010.

Most of our programming projects involve TCP and UDP networking - are there any code examples out there to help me get started with these networking components? Finding a lot of help on the Embarcadero site, but not specifically with UDP/TCP stuff.

TIA


Mike
mknoblock
Active Poster
Active Poster
 
Posts: 13
Joined: Fri Dec 05, 2008 7:01 am

Re: Code examples for CPPB 2010?

Postby gambit47 » Fri Nov 06, 2009 4:14 pm

mknoblock wrote:Most of our programming projects involve TCP and UDP networking - are there any code examples out there to help me get started with these networking components?


Not without first knowing which components you are using to begin with.

mknoblock wrote:Finding a lot of help on the Embarcadero site, but not specifically with UDP/TCP stuff.


What exactly do you need to know? There are no differences in TCP/UDP themselves between BCB 5 and BCB 2010, but the component wrappers you are using may have version-specific issues.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
gambit47
BCBJ Author
BCBJ Author
 
Posts: 974
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Code examples for CPPB 2010?

Postby mknoblock » Fri Nov 06, 2009 4:49 pm

For Builder 5, I drop a TNMUDP component on the form and set its LocalPort property to 5361. Then I double-click on the OnDataReceived event in the Object Inspector to create the DataReceived() event. In the event, I put anything like

int numbytes = NumberBytes;

and put a breakpoint on it. Compile and run, and after a few seconds the breakpoint hits ( I have this udp traffic on my network all the time).

If I repeat the process in Builder 2010 the breakpoint never hits:
Drop TUdpSocket; set Active=true; blockMode=bmNonBlocking; LocalPort=5361
Double-click OnReceive event, int k=DataLen; set breakpoint; compile and run.

I have no doubt it's something trivial with respect to this particular component, but there are no usage examples in help. I tried Open() and Connect() events with no luck.
mknoblock
Active Poster
Active Poster
 
Posts: 13
Joined: Fri Dec 05, 2008 7:01 am

Re: Code examples for CPPB 2010?

Postby gambit47 » Mon Nov 09, 2009 1:58 am

mknoblock wrote:If I repeat the process in Builder 2010 the breakpoint never hits


That is because TUdpSocket is not designed to work the way you are thinking. It is NOT an asynchronous event-driven component like TNMUDP was. Its OnReceive event is only called when ReceiveBuf() or ReceiveFrom() is called by your code. To accomplish what you are looking for, you would have to call one of those methods in a continuously running timer. For that matter, TUdpSocket is a CLX component, not a VCL component, and CLX is a dead technology, so you should avoid using it.

Since you are using CB2010, I would suggest looking at Indy, which ships with the IDE. Its TIdUDPServer component behaves more like what you are looking for.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
gambit47
BCBJ Author
BCBJ Author
 
Posts: 974
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Code examples for CPPB 2010?

Postby mknoblock » Mon Nov 09, 2009 7:44 am

OK; TIdUDPServer does break on a receive event, and it looks like ReceiveBuffer() is what I need. The compiler won't allow this:

void __fastcall TForm2::UDPUDPRead(TIdUDPListenerThread *AThread, TBytes AData,
TIdSocketHandle *ABinding)
{
int count,port;
char buf[1200];
String IP;
count = (TIdBaseComponent *)UDP->ReceiveBuffer(buf,IP,port,IdTimeoutDefault);
}

[BCC32 Error] Unit2.cpp(29): E2285 Could not find a match for 'TIdUDPBase::ReceiveBuffer(char *,UnicodeString,int,const signed char)'
Full parser context
Unit2.cpp(24): parsing: void _fastcall TForm2::UDPUDPRead(TIdUDPListenerThread *,TByteDynArray,TIdSocketHandle *)


And so it goes... you see my next question: 'How do I send', followed by 'How do I do the same with TCP', etc. Code examples for very basic usage of Indy10 with Builder 2010 would be great; or a nice big Amazon book. With no reference material, I can't leverage my years of socket programming in BUilder 5, and come to a screeching halt when trying to upgrade.
mknoblock
Active Poster
Active Poster
 
Posts: 13
Joined: Fri Dec 05, 2008 7:01 am

Re: Code examples for CPPB 2010?

Postby gambit47 » Mon Nov 09, 2009 1:44 pm

mknoblock wrote:OK; TIdUDPServer does break on a receive event, and it looks like ReceiveBuffer() is what I need.


Actually no, it is not, in this situation. TIdUDPServer automatically reads incoming data for you before then firing the OnUDPRead event. The event handler's AData parameter contains the actual data, for example:

Code: Select all
void __fastcall TForm2::UDPUDPRead(TIdUDPListenerThread *AThread, TBytes AData, TIdSocketHandle *ABinding)
{
    char buf[1200];
    int count = min(AData.Length, 1200);
    RawToBytes(AData, buf, count);
    String IP = ABinding->PeerIP;
    int port = ABinding->PeerPort;
    ...
}


mknoblock wrote:The compiler won't allow this


That is because you are passing the wrong parameters to ReceiveBuffer(). Its ABuffer parameter accepts a reference to a TIdBytes variable, but you are trying to pass it a char[] pointer instead. Also, its APort parameter accepts a reference to a TIdPort variable, but you are trying to pass it an integer instead. The correct use of ReceiveBuffer() would be more like this instead:

Code: Select all
int count;
TIdPort port;
TIdBytes buf;
String IP;
buf.Length = 1200;
count = UDP->ReceiveBuffer(buf, IP, port, IdTimeoutDefault);
buf.Length = count;
...


mknoblock wrote:you see my next question: 'How do I send'


If you want to send data inside the OnUDPRead event back to the original client, then use the ABinding->SendTo() method, for example:

Code: Select all
void __fastcall TForm2::UDPUDPRead(TIdUDPListenerThread *AThread, TBytes AData, TIdSocketHandle *ABinding)
{
    ...
    ABinding->SendTo(ABinding->PeerIP, ABinding->PeerPort, A_TIdBytes_Buffer_Here);
}


mknoblock wrote:followed by 'How do I do the same with TCP', etc.


TCP is a very different beast then UDP. Look at the TIdTCPClient and TIdTCPServer components, and the TIdIOHandler class. UDP is a message-based transport, whereas TCP is a bytestream-based transport, so you will have to change your reading/writing logic a little bit so you know how many bytes are being sent per each TCP "message". When sending a block of data, send how many bytes are in the block before sending the actual block. When receiving, read the block size first, then read however many bytes it says to read. For example:

Code: Select all
{
    ...
    TCPClient->IOHandler->Write(SizeOfReqData);
    TCPClient->IOHandler->Write(ReqData);
    int len = TCPClient->IOHandler->ReadLongint();
    TIdBytes reply;
    TCPClient->IOHandler->ReadBytes(reply, len, false);
    // use reply as needed...
}

void __fastcall TForm1::IdTCPServer1Execute(TIdContext *AContext)
{
    int len = AContext->Connection->IOHandler->ReadLongint();
    TIdBytes buf;
    AContext->Connection->IOHandler->ReadBytes(buf, len, false);
    // use bytes as needed...
    ...
    AContext->Connection->IOHandler->Write(SizeOfReplyData);
    AContext->Connection->IOHandler->Write(ReplyData);
}


Of course, there are many different ways to read/write data with TCP, depending on what kind of data you are actually trying to send back and forth.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
gambit47
BCBJ Author
BCBJ Author
 
Posts: 974
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Code examples for CPPB 2010?

Postby mknoblock » Mon Nov 09, 2009 3:40 pm

Thanks for the code; the ReceiveBuffer() call works.

I did have a compile problem with RawToBytes, though:

TIdBytes buf2 = RawToBytes(Adata,count);

results in this:
[BCC32 Error] Unit2.cpp(37): E2034 Cannot convert 'TByteDynArray' to 'const void *'

Guess the world has changed since BCB5 - looks like Strings are Unicode by default now. Anyway, your code samples are enough to get me started; I appreciate it.

Mike
mknoblock
Active Poster
Active Poster
 
Posts: 13
Joined: Fri Dec 05, 2008 7:01 am

Re: Code examples for CPPB 2010?

Postby gambit47 » Tue Nov 10, 2009 1:00 pm

mknoblock wrote:I did have a compile problem with RawToBytes, though


Sorry, my bad. I meant to call BytesToRaw() instead of RawToBytes():

Code: Select all
void __fastcall TForm2::UDPUDPRead(TIdUDPListenerThread *AThread, TBytes AData, TIdSocketHandle *ABinding)
{
    char buf[1200];
    int count = min(AData.Length, 1200);
    BytesToRaw(AData, buf, count);
    ...
}
Remy Lebeau (TeamB)
Lebeau Software
User avatar
gambit47
BCBJ Author
BCBJ Author
 
Posts: 974
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA


Return to Technical

Who is online

Users browsing this forum: Bing [Bot] and 4 guests

cron