Thread View: borland.public.cppbuilder.internet.socket
3 messages
3 total messages
Started by jesse
Thu, 24 Apr 2008 19:25
Can a TIdUDPClient "listen" on a local port?
Author: jesse
Date: Thu, 24 Apr 2008 19:25
Date: Thu, 24 Apr 2008 19:25
43 lines
2372 bytes
2372 bytes
I've been trying to set up a UDP communication where the communication
is "one way." I assumed I could use TIdUDPClients for both ends. I
was not able to get this working because I couldn't find a way to get
a TIdUDPClient to listen on a local port.
Is it possible to get TIdUDPClient to "listen" on a local port on the
receiving side of the communication?
Here is the "server" side sample code:
__fastcall InputThread::InputThread(bool CreateSuspended, char*
ipAddress, int portNumber)
: TThread(CreateSuspended)
{
udpClient = new TIdUDPClient(NULL);
this->ipAddress = ipAddress;
this->portNumber = portNumber;
udpClient->Active = true;
}
void __fastcall InputThread::Execute()
{
TIdBytes buffer;
int count, portNumber;
AnsiString ipAddress;
while(!Terminated) {
udpClient->ReceiveBuffer(buffer, ipAddress, portNumber,
IdTimeoutInfinite);
if(ipAddress.ToInt() != this->ipAddress)
continue;
for(int i=0; i < cont; ++i) {
outFile << buffer[i];
}
}
if(outFile.is_open())
outFile.close();
udpClient->Active = false;
}
The "client" side of the code is working, I am capturing the packets
with wireshark.
Jesse
Re: Can a TIdUDPClient "listen" on a local port?
Author: jesse
Date: Thu, 24 Apr 2008 19:41
Date: Thu, 24 Apr 2008 19:41
9 lines
1578 bytes
1578 bytes
On Apr 24, 3:25 pm, jesse <je...@goerz.us> wrote: > void __fastcall InputThread::Execute() ... > udpClient->ReceiveBuffer(buffer, ipAddress, portNumber, > IdTimeoutInfinite); this line should have been count = udpClient->ReceiveBuffer(buffer, ipAddress, portNumber, IdTimeoutInfinite);
Re: Can a TIdUDPClient "listen" on a local port?
Author: jesse
Date: Tue, 29 Apr 2008 18:57
Date: Tue, 29 Apr 2008 18:57
121 lines
5244 bytes
5244 bytes
On Apr 24, 3:41 pm, jesse <je...@goerz.us> wrote:
> On Apr 24, 3:25 pm, jesse <je...@goerz.us> wrote:
>
> > void __fastcall InputThread::Execute()
> ...
> > udpClient->ReceiveBuffer(buffer, ipAddress, portNumber,
> > IdTimeoutInfinite);
>
> this line should have been
> count = udpClient->ReceiveBuffer(buffer, ipAddress, portNumber,
> IdTimeoutInfinite);
It appears the answer is no. What I wanted was to have a blocking
UDPServer. I thought the UDPListenerThread was going to make things
more complicated. An "article" here (scroll down or search for
TIdUDPServer):
http://conferences.codegear.com/article/32159
Gives this explanation:
================
When active it creates a listening thread to listen for inbound UDP
packets. For each UDP packet received, it fires the OnUDPRead event.
When ThreadedEvent is false, the OnUDPRead event will be fired in the
context of the main program thread. When ThreadedEvent is true, the
OnUDPRead event is fired in the context of the listener thread.
TIdUDPServer does not spawn peer threads for each connection
regardless of the setting of ThreadedEvent. When ThreadedEvent is true
or false, its execution will block the receiving of more messages.
Because of this the processing of the OnUDPRead event should be quick,
or should spawn off additional threads to handle lengthy tasks.
================
So, I can just use OnUDPRead as the blocking read process. The
documentation does not mention this anywhere. The above ought to be
inserted directly into the TIdUDPServer description. In case anyone
stumbles through here (untested):
class InputThread : public TThread
{
private:
TIdUDPServer* udpServer;
AnsiString ipAddress;
TIdBytes TIdBuffer;
bool newData;
int newDataCount;
TCriticalSection* udpLock;
void __fastcall udpReadHandler(TObject *Sender,
TIdBytes AData,
TIdSocketHandle *ABinding);
protected:
void __fastcall Execute();
void __fastcall OnTerminate();
}
__fastcall InputThread::InputThread(bool CreateSuspended,
char* ipAddress,
int portNumber)
: TThread(CreateSuspended)
{
this->ipAddress = ipAddress;
udpServer = new TIdUDPServer(NULL);
udpServer->DefaultPort = portNumber;
udpServer->BroadcastEnabled = false;
udpServer->ThreadedEvent = true; // handle synchronization manually
udpServer->OnUDPRead = udpReadHandler;
udpServer->Active = true;
}
void __fastcall InputThread::Execute()
{
while(!Terminated) {
// TIdUDPListener thread blocks receiving new connections (aka
messages) when
// it calls back to udpReadHandler. We copy new data and release
it so
// it can "unblock." We protect the sentinel newData with
// the semaphore udpLock.
udpLock->Acquire();
if(newData == true) {
// If we need to make a copy do it here (is this on the heap or
stack?)
newData = false;
udpLock->Release();
// process data here so ListenerThread can go get more
messages...
}
else {
udpLock->Release();
// We need to release the processor to do work, we don't want
// this thread to busy wait and starve off the rest of the
threads.
// I can't find a yield() function, but this should accomplish
the
// same thing...
Sleep((unsigned long) 1); // Sleep for ~ 1ms (release processor)
}
} // End of while
udpServer->Active = false;
}
void __fastcall InputThread::udpReadHandler(TObject *Sender, TIdBytes
AData, TIdSocketHandle *ABinding)
{
int count = AData.get_length();
if((count == 0) || (ABinding->PeerIP != this->ipAddress))
return;
udpLock->Acquire();
TIdBuffer = AData.Copy(); // passes a reference (is this on the
heap?)
newData = true;
newDataCount = count;
udpLock->Release();
}
Jesse
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads