🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.internet.socket
Article #94

Re: Can a TIdUDPClient "listen" on a local port?

#94
From: jesse
Date: Tue, 29 Apr 2008 18:57
121 lines
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
Technical Details
Message-ID: <c9721237-59de-4b0b-8f69-447522454b90@24g2000hsh.googlegroups.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!postnews.google.com!24g2000hsh.googlegroups.com!not-for-mail
References: <8c25e27d-8591-473a-8149-de7dfa535aae@m3g2000hsc.googlegroups.com> <b7d12f07-63eb-4fae-aa17-dc4119f6fcd0@b64g2000hsa.googlegroups.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,de53d11d394597e
X-Google-Attributes: gid11508e,domainid0,public,usenet
X-Google-Language: ENGLISH,ASCII-7-bit
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!postnews.google.com!24g2000hsh.googlegroups.com!not-for-mail
From: jesse <jesse@goerz.us>
Newsgroups: borland.public.cppbuilder.internet.socket
Subject: Re: Can a TIdUDPClient "listen" on a local port?
Date: Tue, 29 Apr 2008 11:57:38 -0700 (PDT)
Organization: http://groups.google.com
Lines: 121
Message-ID: <c9721237-59de-4b0b-8f69-447522454b90@24g2000hsh.googlegroups.com>
References: <8c25e27d-8591-473a-8149-de7dfa535aae@m3g2000hsc.googlegroups.com> 
 <b7d12f07-63eb-4fae-aa17-dc4119f6fcd0@b64g2000hsa.googlegroups.com>
NNTP-Posting-Host: 128.217.77.16
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-Trace: posting.google.com 1209495459 32033 127.0.0.1 (29 Apr 2008 18:57:39 GMT)
X-Complaints-To: groups-abuse@google.com
NNTP-Posting-Date: Tue, 29 Apr 2008 18:57:39 +0000 (UTC)
Complaints-To: groups-abuse@google.com
Injection-Info: 24g2000hsh.googlegroups.com; posting-host=128.217.77.16; 
 posting-account=6q83zQoAAABx03s3-G4Ic6LwTjCEzh3b
User-Agent: G2/1.0
X-HTTP-UserAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.14) 
 Gecko/20080404 Firefox/2.0.0.14,gzip(gfe),gzip(gfe)