Search code examples
socketsdelphiudpindy

Indy UPDServer in windows service not listening


I made a windows service wich is going to run in a server machine, and must listen client's requests to send files to them by UDP. I made the client application, and now I am trying to send UDP messages to the server, but the UDPRead procedure seems to not being called. I am working with Delphi XE7 in windows 10. The testing environment is:

  • Client: Form application, with TIdUDPServer listening at port 27905. Sends and receives data correctly.
  • Server: Windows service, with TIdUDPServer listening at port 27906. Sends data correctly with TIdUDPServer.Send, but it doesn't receive anything.
  • Firewall and antivirus deactivated, just in case.
  • Packages are being sent to the IP 127.0.0.1

I verified that the problem is the windows service because I harcoded a TIdUDPServer.Send in the Create method of the windows service's main class just to see if the client app receives it, and it does. Besides, I have sent UDP packages from the client to another form application that I recently developed to see if it is receiving data, and it does.

I am creating the TIdUDPServer object in the windows service app like this:

UDP := TIdUDPServer.Create(nil);
UDP.OnUDPRead := UDPRead;
UDP.DefaultPort := pListenPort;
UDP.Bindings.Clear;
UDP.Bindings.Add.IPVersion:=Id_IPv4;
UDP.Active := True;

And the procedure declaration is:

procedure TRed.UDPRead(AThread: TIdUDPListenerThread; const AData: TidBytes; ABinding: TIdSocketHandle);

Probably I am missing something, but I can't find why is the UDPServer failing in the windows service. Any clue will be appreciated, thank you in advance.


Solution

  • TIdUDPServer uses a worker thread to read incoming data in a loop, firing the OnUDPRead event whenever new data arrives.

    By default, the OnUDPRead event handler is triggered by a call to TThread.Synchronize(), which means it fires in the context of the main UI thread (or at least any thread that calls the RTL's CheckSynchronize() function), not in the UDP worker thread. Chances are that your service is not processing Synchronize() requests, which would explain why the event handler never fires.

    So, you have two possible options:

    1. Have your service call CheckSynchronize() periodically, such as in its OnExecute event. Then the OnUDPRead event will fire in the context of the service thread.

    2. set the TIdUDPServer.ThreadedEvent property to true (it is false by default). When ThreadedEvent is true, the UDP worker thread bypasses Synchronize() and fires the OnUDPRead event directly. As such, you would just have to make sure that your event handler contains thread-safe code inside of it.