Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2016-04

fpSelect fails with UDP sockets?

6 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Klaus Hartnegg

Hello,

Does fpSelect not work with UDP sockets?
It always returns 0, which means it did not see a packet. Is anything wrong with this code?

Uses
   UnixType, BaseUnix, Sockets;
procedure abort (reason:string);
begin
   writeln (reason);
   halt;
end;
var
   sock: cint;
   adr : {TInet}SockAddr;
   rc  : cint;
   FDS : Tfdset;
begin
   sock := fpSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
   if sock = -1 then
      abort ('Error from fpSocket');
   adr.sin_family      := AF_INET;
   adr.sin_addr.s_addr := INADDR_ANY;
   adr.sin_port        := htons(53);
   rc := fpBind (sock, @adr, sizeof(adr));
   if rc  0 then
      abort ('Error from fpBind');
   Writeln ('send udp packet in less than 5 seconds');
   Fpfd_zero(FDS);
   FpFd_set (sock,FDS);
   rc := fpSelect (1,@FDS,nil,nil,5000);
   if rc = -1 then
      abort ('Error from fpSelect');
   if rc > 0 then
     Writeln ('Thank you !')
   else
     Writeln ('Too late !');
end.

Reply by email

Mark Morgan Lloyd
to Klaus Hartnegg
Klaus Hartnegg wrote 5 lines
Hello, Does fpSelect not work with UDP sockets? It always returns 0, which means it did not see a packet. Is anything wrong with this code?

I don't have time to play with that right now, but test it with a port > 1024 before trying a lower-numbered one. What OS are you running on- the select() semantics vary slightly on Linux compared with e.g. Solaris, and I don't know where e.g. BSD stands on this.

Show quoted text 38 lines
Uses UnixType, BaseUnix, Sockets; procedure abort (reason:string); begin writeln (reason); halt; end; var sock: cint; adr : {TInet}SockAddr; rc : cint; FDS : Tfdset; begin sock := fpSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if sock = -1 then abort ('Error from fpSocket'); adr.sin_family := AF_INET; adr.sin_addr.s_addr := INADDR_ANY; adr.sin_port := htons(53); rc := fpBind (sock, @adr, sizeof(adr)); if rc 0 then abort ('Error from fpBind'); Writeln ('send udp packet in less than 5 seconds'); Fpfd_zero(FDS); FpFd_set (sock,FDS); rc := fpSelect (1,@FDS,nil,nil,5000); if rc = -1 then abort ('Error from fpSelect'); if rc > 0 then Writeln ('Thank you !') else Writeln ('Too late !'); end.
Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Klaus Hartnegg
to Klaus Hartnegg: Does fpSelect not work with UDP sockets? It always returns 0, which means it did not see…
It works with
   rc := fpSelect (sock+1,@FDS,nil,nil,5000);

I did not understand the description of the first argument in the docs, so I used the value from the sample, this was not a good idea.

For reference here is the source that works:

Uses
   UnixType, BaseUnix, Sockets;
procedure abort (reason:string);
begin
   writeln (reason);
   halt;
end;
var
   sock: cint;
   ladr : SockAddr;
   radr : SockAddr;
   adrlen: tSockLen;
   msg : string[255];
   FDS : Tfdset;
   rc  : cint;
begin
   sock := fpSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
   if sock = -1 then
      abort ('Error from fpSocket');
   ladr.sin_family      := AF_INET;
   ladr.sin_addr.s_addr := INADDR_ANY;
   ladr.sin_port        := htons(2000);
   rc := fpBind (sock, @ladr, sizeof(ladr));
   if rc  0 then
      abort ('Error from fpBind');
   adrlen := sizeof(radr);
   Fpfd_zero (FDS);
   FpFd_set (sock,FDS);
   rc := fpSelect (sock+1,@FDS,nil,nil,5000);
   writeln (rc);
   if rc = -1 then
      abort ('Error from fpSelect');
   if rc = 0 then
      abort ('timeout');
   rc := fpRecvFrom (sock, @msg[1], 255, 0 {flags}, @radr, @adrlen);
   if rc = -1 then
      abort ('Error from FpRecv');
   if rc > 255 then
      rc := 255;
   msg[0] := chr(rc);
   writeln (msg);
end.

And this is the sender:

Uses
   UnixType, BaseUnix, Sockets;
procedure abort (reason:string);
begin
   writeln (reason);
   halt;
end;
var
   sock: cint;
   sadr: {TInet}SockAddr;
   dadr: {TInet}SockAddr;
   adrlen: tSockLen;
   msg : string;
   rc  : cint;
begin
   sock := fpSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
   if sock = -1 then
      abort ('Error from fpSocket');
   sadr.sin_family      := AF_INET;
   sadr.sin_addr.s_addr := INADDR_ANY;
   sadr.sin_port        := 0; { auto-select }
   rc := fpBind (sock, @sadr, sizeof(sadr));
   if rc  0 then
      abort ('Error from fpBind');
   dadr.sin_family := AF_INET;
   dadr.sin_addr.s_bytes[1] := 127;
   dadr.sin_addr.s_bytes[2] := 0;
   dadr.sin_addr.s_bytes[2] := 0;
   dadr.sin_addr.s_bytes[2] := 1;
   dadr.sin_port   := htons(2000);
   adrlen := sizeof(dadr);
   msg := 'hello, world!';
   rc := fpSendTo (sock, @msg[1], length(msg), 0 {flags}, @dadr, adrlen);
   if rc = length(msg) then
      writeln ('ok');
end.

Reply by email

Klaus Hartnegg
to Klaus Hartnegg
Klaus Hartnegg wrote
dadr.sin_addr.s_bytes[1] := 127; dadr.sin_addr.s_bytes[2] := 0; dadr.sin_addr.s_bytes[2] := 0; dadr.sin_addr.s_bytes[2] := 1;

The array index numbers are of course garbage (from incomplete copy&paste editing), but somehow it worked nevertheless.

Should have been
   dadr.sin_addr.s_bytes[1] := 127;
   dadr.sin_addr.s_bytes[2] := 0;
   dadr.sin_addr.s_bytes[3] := 0;
   dadr.sin_addr.s_bytes[4] := 1;

Loopback appears to catch the whole loopback network, not just that single address.

Reply by email

Unknown author
to Klaus Hartnegg: It works with rc := fpSelect (sock+1,@FDS,nil,nil,5000); I did not understand the…
Klaus Hartnegg wrote 5 lines
dadr.sin_family := AF_INET; dadr.sin_addr.s_bytes[1] := 127; dadr.sin_addr.s_bytes[2] := 0; dadr.sin_addr.s_bytes[2] := 0; dadr.sin_addr.s_bytes[2] := 1;

shouldn't this be

   dadr.sin_addr.s_bytes[1] := 127;
   dadr.sin_addr.s_bytes[2] := 0;
   dadr.sin_addr.s_bytes[3] := 0;
   dadr.sin_addr.s_bytes[4] := 1;

NOTE: i've not done any research to see what dadr.sin_addr.s_bytes is but i assume that it is an array of bytes to contain each of the IP address parts...

NOTE: No off-list assistance is given without prior approval. *Please keep mailing list traffic on the list* unless private contact is specifically requested and granted.

Reply by email

Mark Morgan Lloyd
to Unknown author
NOTE: i've not done any research to see what dadr.sin_addr.s_bytes is but i assume that it is an array of bytes to contain each of the IP address parts...

It's usually an untagged variant record so you can also do something like

target.s_addr:= HToNL($7F000001);

Just /don't/ assume you can do maths with it.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email