Jump to content

Recommended Posts

Hello,

 

in my project I ue ICS V8.62 in Delphi 10.3.3 to detect some devices on the network per UDP.

Sometimes my routine works as expected and sometimes it crashes.

 

When it crashes it happens on a call to Socket.MessagePump and inside that one
on the call to Application.ProcessMessages.

 

My code is inside an Button click handler and it immediately crashes when pressing F7 in
the debugger on Application.ProcessMessages. Since it's a VCL app unit forms is used.

 

Application is assigned.
My socket is a plain TWSocket, Proto is 'UDP' and local IP is set to one of the interfaces the computer
has to search on that one and LocalPort is 0.

 

I call Socket.Connect and then immediately Socket.MessagePump where it crashes in.

 

Anybody any clue?

Share this post


Link to post

If you are connecting to another device, you don't need to set a local IP address, use 0.0.0.0 and let Windows worry about it.  Sometimes interfaces come and go, that could cause an error.  

 

Local address is really for listening sockets, although can be used on servers with multiple IP addresses to select an outgoing address.

 

Angus

 

Share this post


Link to post

I do set the interface because it is a broadcast to 255.255.255.255 and I want it to go out to all interfaces.

But: would that be really connected to the MessagePump crash in Application.ProcessMessages?

Share this post


Link to post

I have never seen a message pump crash with ICS.  But I know using a non-existent interface will fail.  Been a long time since I did a project with UDP broadcasts. 

 

Angus

 

Share this post


Link to post

In order to obtain the list of interfaces I loop through I use IcsGetInterfaceList.

This returns 3 interfaces to me: 127.0.0.1 (loopback), which I skip, 10.149.x.y (x and y have valid numbers)
which is the IP of that VM I'm running in and the last one is 0.0.0.0.

 

This is my code:

Socket := TWSocket.Create(nil);

Socket.Proto           := 'UDP';
Socket.Addr            := '255.255.255.255';
Socket.Port            := '1234';
Socket.LineMode        := false;
Socket.OnDataAvailable := OnUDPDataAvailable;

Addr.S_addr := IfList[i]^.iiAddress.AddressIn.sin_addr.S_addr;
Socket.LocalAddr       := string(WSocket_inet_ntoa(Addr));
Socket.LocalPort       := '0';

Socket.Connect;

Socket.MessagePump;
Socket.SendLine('Hallo?');

OnUDPDataAvailable is declared as method like this:

 

procedure TMyClass.OnUDPDataAvailable(Sender: TObject; ErrCode: Word);

Edited by TurboMagic

Share this post


Link to post
11 minutes ago, Fr0sT.Brutal said:

Why do you need Socket.MessagePump at all?

I know that it would be better to not use it. It often works, but just not always.

In my case the routine running this shall already return the list of the search so after the code fragment shown in my post above,
which is in a loop going through all interfaces determined as plausible ones, I have a waiting loop so received answers which are
noted in some list have time to arrive. It's just to find out if a device answers to this request so it is present and to get it's IP.

Share this post


Link to post

Using a redundant MessagePump without threads is untested and certainly serves no purpose before making any requests or listening.  If you remove it, does the code work? 

 

The LocalIPList function is an easier way to get a list of addresses as strings, you need to set family and IPPROTO_UDP protocol, the default is TCP only.

 

Angus

 

 

 

Share this post


Link to post
58 minutes ago, TurboMagic said:

I know that it would be better to not use it. It often works, but just not always.

From the code above I see you just trying to use async event-driven classes in sync mode. While this approach appears in several places in ICS itself, it's not a recommended way of using. You must understand the consequences. The simplest example is: if you launch this code from button click, MessagePump will retrieve and dispatch all Windows messages so the button will be unpushed and user will be able to push it again.

P.S. In fact, I never used this function so I could be wrong here. I'm surprised to see it in ICS methods besides TCustomSyncWSocket.WaitUntilReady.

Edited by Fr0sT.Brutal

Share this post


Link to post
1 hour ago, TurboMagic said:

Socket.Connect;
Socket.MessagePump;
Socket.SendLine('Hallo?');

 

Don't do that. Use OnSessionConnected event and write a handler which checks if connection is successful and if it is, can SendLine to send something.

 

Share this post


Link to post

Is there really such an OnSessionConnected  event on a connection less UDP socket?

Remember: I'm using UDP here.

Edited by TurboMagic

Share this post


Link to post
9 minutes ago, TurboMagic said:

Is there really such an OnSessionConnected  event on a connection less UDP socket?

Yes, there is so that the use of TWSocket is the same for both TCP and TCP.

Look at the source code if you are interested.

Share this post


Link to post

Yes, OnSessionConnected event is fired for UDP, but should be virtually instantaneous since no traffic is sent, you should have waited until the state changed before sending anything, but send would just fail and you are ignoring errors and it would not explain the exception. 

 

Angus

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×