Jump to content
Clément

Receiving UDP packet fails 2 times with 10014 and works

Recommended Posts

Hi,

 

I'm using 12.1 with ICS 8.69.

 

This code is driving me nuts.

 

procedure TDiscoverClient.event_ServerReply(aSender: TObject;
  ErrCode: Word);
const
  _BufferSize = 1024;
begin
  if errCode = 0 then
  begin
     var lBuffer : Tbytes ;
     var lFromSock : TSockAddr;
     var lFromLen  : Integer;
     var lCount    : Integer;
     SetLength( lBuffer, _BufferSize );
     lcount := fSender.ReceiveFrom(@lBuffer[0], _BufferSize, lFromSock, lFromLen );
     if lCount>0 then
     begin
        if Assigned( fOnHostFound ) or Assigned(fOnHostAlive) then
        begin
           var lRespParts := SplitString( TEncoding.ANSI.GetString( lBuffer,0,lCount ),':');
           var lServerMachineName := '';
           var lServerMachineIP   : String := String(inet_ntoa(lFromSock.sin_addr));
           if lRespParts[0] = 'M' then
             lServerMachineName := lRespParts[1];

           if Assigned(fOnHostFound) then fOnHostFound(Self, lServerMachineIP,lServerMachineName );
           if Assigned(fOnHostAlive) then fOnHostAlive(Self, lServerMachineIP,lServerMachineName );
        end;
     end
     else
       fErrMsg := Ics_WSAGetLastError;

  end;

end;

The code is executed from a child form, from my main VCL application.
I need to check if a UDP server is alive ( or found). Anyway, I always get 2 times lCount = -1, and fErrMsg is assigned 10014 both times, the 3rd times it works and shows correctly the expected information.
I tried several combinations to allocate lBuffer, and every one fails with 10014 the first 2 times, and the third is goes. 
The client machine, where this code runs, has only IPv4 active. The UDP server runs both IPv6 and IPv4, but is only bound to Ipv4 at 0.0.0.0

 

Can someone shed some light?

 

TIA,

Clément
 

Share this post


Link to post

Winsock error 10014 is WSAEFAULT. I don't know ICS's internals, but presumably fSender.ReceiveFrom() calls Winsock's recvfrom() function, whose documentation says:

Quote

WSAEFAULT
The buffer pointed to by the buf or from parameters are not in the user address space, or the fromlen parameter is too small to accommodate the source address of the peer address.

Your lFromLen variable is uninitialized, so your code is passing an indeterminate value to recvfrom() which exhibits undefined behavior. Sometimes the value is too small, sometimes it is not.  You need to initialize your lFromLen variable to specify the size of your lFromSock variable before calling fSender.ReceiveFrom().

 

On a side note: you are treating lCount=0 as an error condition, but it is not. Unlike TCP, UDP messages can be 0 bytes in size. You should be calling WSAGetLastError() only if lCount is SOCKET_ERROR (-1).

Edited by Remy Lebeau

Share this post


Link to post

I would recommend you use the TIcsIpStrmLog streaming log component, look at the doSocketRemoteClick function in the Snippets sample which is TCP so needs a one line change for UDP, then data just arrives in an event.

 

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
×