Recent

Author Topic: cannot receive messages; udp server with lnet  (Read 13495 times)

prodingus

  • Jr. Member
  • **
  • Posts: 83
Re: cannot receive messages; udp server with lnet
« Reply #30 on: July 02, 2022, 11:18:45 pm »
Quote
The socketError will give you more information when your fpbind() fails.

this is the problem! it returns 10022 error. The code is running ON THE "SERVER" and the ip of that "server" is 1.1.1.2.  %). Also, no firewall.
« Last Edit: July 02, 2022, 11:22:20 pm by prodingus »
lazarus 2.2.0, FPC 3.2.2

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: cannot receive messages; udp server with lnet
« Reply #31 on: July 02, 2022, 11:36:38 pm »
This error is the EINVAL error, from the WinSock2 Documentation for bind:
Quote
An invalid argument was supplied.

This error is returned of the socket s is already bound to an address.

Is the code you posted previously the exact code that results in this error?

prodingus

  • Jr. Member
  • **
  • Posts: 83
Re: cannot receive messages; udp server with lnet
« Reply #32 on: July 02, 2022, 11:39:29 pm »
Quote
The rather hackish way I'd do it would be something like

Code: Pascal  [Select][+][-]
  1.     uses
  2.       sockets;
  3.      
  4.     const
  5.       UDPPackLen = 512;
  6.  
  7.     var
  8.       sock: Tsocket;
  9.       buff: String;
  10.       ServerAddr, FromAddr: sockaddr_in;
  11.       FromAddrLen: Integer;
  12.       ClientAddr: String;
  13.       ClientPort: Word;
  14.       MessageSize: SizeInt;
  15.     begin
  16.       // Start UDP Server
  17.       sock := fpsocket(AF_INET, SOCK_DGRAM, 0);
  18.       ServerAddr.sin_family:= AF_INET;
  19.       ServerAddr.sin_addr := StrToNetAddr('1.1.1.2'); // server IP
  20.       ServerAddr.sin_port := 531; // server port
  21.       fpbind(sock, @ServerAddr, SizeOf(ServerAddr));
  22.       // Receive Data
  23.       SetLength(buff, UDPPackLen);
  24.       MessageSize := fprecvfrom(sock, @buff[1], Length(buff), 0, @FromAddr, @FromAddrLen);
  25.       SetLength(buff, MessageSize);
  26.       ClientAddr := NetAddrToStr(FromAddr.sin_addr);
  27.       ClientPort := NToHs(FromAddr.sin_port);
  28.       WriteLn(buff)
  29.     end.

even this returns 10022
lazarus 2.2.0, FPC 3.2.2

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: cannot receive messages; udp server with lnet
« Reply #33 on: July 02, 2022, 11:41:23 pm »
Quote
The socketError will give you more information when your fpbind() fails.

this is the problem! it returns 10022 error. The code is running ON THE "SERVER" and the ip of that "server" is 1.1.1.2.  %). Also, no firewall.
Did you also try my same Sender code I gave you?
Or are you using your own (which we haven't seen yet)?

Just try my Sender and Reciever code.


prodingus

  • Jr. Member
  • **
  • Posts: 83
Re: cannot receive messages; udp server with lnet
« Reply #34 on: July 02, 2022, 11:43:57 pm »
Quote
Is the code you posted previously the exact code that results in this error?

Quote
Did you also try my same Sender code I gave you?

Yes its the same code (before the sender receiver, I haven't tried them yet). And I did a system reboot. Nothing else networking is running.


lazarus 2.2.0, FPC 3.2.2

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: cannot receive messages; udp server with lnet
« Reply #35 on: July 02, 2022, 11:48:22 pm »
The error is not the bind but the recvfrom, and the error here is because thanks to some weird quirk of WinSock, recvfrom does not like it if the address is located on the stack (or unaligned memory in general).

The quick solution to this is to put the address and length on the heap:
Code: Pascal  [Select][+][-]
  1.         uses
  2.           sockets;
  3.          
  4.         const
  5.           UDPPackLen = 512;
  6.      
  7.         var
  8.           sock: Tsocket;
  9.           buff: String;
  10.           ServerAddr: sockaddr_in;
  11.           FromAddr: Psockaddr_in;
  12.           FromAddrLen: PInteger;
  13.           ClientAddr: String;
  14.           ClientPort: Word;
  15.           MessageSize: SizeInt;
  16.         begin
  17.           // Start UDP Server
  18.           sock := fpsocket(AF_INET, SOCK_DGRAM, 0);
  19.           ServerAddr.sin_family:= AF_INET;
  20.           ServerAddr.sin_addr := StrToNetAddr('1.1.1.2'); // server IP
  21.           ServerAddr.sin_port := 531; // server port
  22.           fpbind(sock, @ServerAddr, SizeOf(ServerAddr));
  23.           // Receive Data
  24.           SetLength(buff, UDPPackLen);
  25.           new(FromAddr);
  26.           new(FromAddrLen);
  27.           try
  28.             FromAddrLen^ := SizeOf(FromAddr^);
  29.             MessageSize := fprecvfrom(sock, @buff[1], Length(buff), 0, @FromAddr, @FromAddrLen);
  30.             SetLength(buff, MessageSize);
  31.             ClientAddr := NetAddrToStr(FromAddr.sin_addr);
  32.             ClientPort := NToHs(FromAddr.sin_port);
  33.           finally
  34.             Dispose(FromAddr);
  35.             Dispose(FromAddrLen);
  36.           end;
  37.           WriteLn(buff)
  38.         end.

It's just a very weird windows thing, best to not think to much about

Or, as stated above, youse the Unit I posted above: https://github.com/Warfley/PasSimpleSockets/blob/master/simplesockets.pas (example: https://github.com/Warfley/PasSimpleSockets/blob/master/examples/udpechoserver.pas) which also does handle this (as I have encountered this already quite often)
« Last Edit: July 02, 2022, 11:50:15 pm by Warfley »

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: cannot receive messages; udp server with lnet
« Reply #36 on: July 02, 2022, 11:54:04 pm »
The error is not the bind but the recvfrom, and the error here is because thanks to some weird quirk of WinSock, recvfrom does not like it if the address is located on the stack (or unaligned memory in general).
The code I gave didn't use fprecvfrom but fprecv.
So I wonder if TS used my code or again some own changed version?

prodingus

  • Jr. Member
  • **
  • Posts: 83
Re: cannot receive messages; udp server with lnet
« Reply #37 on: July 03, 2022, 12:19:33 am »
Quote
The error is not the bind but the recvfrom, and the error here is because thanks to some weird quirk of WinSock, recvfrom does not like it if the address is located on the stack (or unaligned memory in general).

The quick solution to this is to put the address and length on the heap:

Code: Pascal  [Select][+][-]
  1. new(FromAddr);
  2. new(FromAddrLen);
after this I get again error 10022.

Also after your modifications the lines:
Code: Pascal  [Select][+][-]
  1. ClientAddr := NetAddrToStr(FromAddr.sin_addr);
  2. ClientPort := NToHs(FromAddr.sin_port);
produce error
sockets_1.lpr(41,42) Fatal: Syntax error, ")" expected but "identifier SIN_ADDR" found
sockets_1.lpr(41,42) Fatal: Syntax error, ")" expected but "identifier SIN_PORT" found
lazarus 2.2.0, FPC 3.2.2

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: cannot receive messages; udp server with lnet
« Reply #38 on: July 03, 2022, 12:28:34 am »
Yeah my bad it must be:
Code: Pascal  [Select][+][-]
  1. MessageSize := fprecvfrom(sock, @buff[1], Length(buff), 0, FromAddr, FromAddrLen);
  2.             SetLength(buff, MessageSize);
  3.             ClientAddr := NetAddrToStr(FromAddr^.sin_addr);
  4.             ClientPort := NToHs(FromAddr^.sin_port);
As they are now pointer

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: cannot receive messages; udp server with lnet
« Reply #39 on: July 03, 2022, 12:31:19 am »
Why are you even using fprecvfrom while you don't do anything with the from data?

You can just use fprecv without the fromaddr like I showed in my example.

Did you try my exact code yet?

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: cannot receive messages; udp server with lnet
« Reply #40 on: July 03, 2022, 12:47:59 am »
I think that it is quite important to get recvfrom working, because a UDP server that is not capable of answering is probably quite pointless.

What would be the point if he could get this running using recv when at some point he will need recvfrom probably anyway?

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: cannot receive messages; udp server with lnet
« Reply #41 on: July 03, 2022, 12:54:01 am »
What would be the point if he could get this running using recv when at some point he will need recvfrom probably anyway?
Because the fromadress was already known. It's always the server.

TS hasn't really mentioned what this is used for but from the code it is clear the server is 1.1.1.2.
So the address to anwer to is known.

a client loop that  sends continiously a message (to an ip,port),
and a server loop that listens (receives) for any messages

Ps, I am noob at networking.
Side note: I am using 2 windows 7 vms,  ips are 1.1.1.1 and 1.1.1.2, no firewall.

Besides that... If my code also generates a 10022 error there is something else wrong and it has nothing to do with recvfrom. If it works we can expand it with recvfrom if needed



« Last Edit: July 03, 2022, 01:01:39 am by rvk »

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: cannot receive messages; udp server with lnet
« Reply #42 on: July 03, 2022, 09:33:21 am »
You can just use fprecv without the fromaddr like I showed in my example.

Did you try my exact code yet?

I'd suggest apart from anything else that it's a matter of /courtesy/ to do so, before complaining of ongoing problems.

I agree that RecvFrom() might turn out to be needed as part of the bigger picture, but the first step is to verify that addresses etc. are OK.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: cannot receive messages; udp server with lnet
« Reply #43 on: July 03, 2022, 11:21:49 am »
Because the fromadress was already known. It's always the server.
At least one of us has a misunderstanding here, because I understood it as if he is currently writing the server, and the server probably needs to use recvfrom to identify the client

Besides that... If my code also generates a 10022 error there is something else wrong and it has nothing to do with recvfrom. If it works we can expand it with recvfrom if needed
I could reproduce this error on my machine, and as I already stated, the problem with stack pointers for the memory is something that is known for the winapi for quite some time (and took me a many hours to find out when I first encountered it).
But with this code it works on my machine:
Code: Pascal  [Select][+][-]
  1. uses
  2.   sockets;
  3.  
  4. const
  5.   UDPPackLen = 512;
  6.  
  7. var
  8.   sock: Tsocket;
  9.   buff: String;
  10.   ServerAddr: sockaddr_in;
  11.   FromAddr: psockaddr_in;
  12.   FromAddrLen: PInteger;
  13.   ClientAddr: String;
  14.   ClientPort: Word;
  15.   MessageSize: SizeInt;
  16. begin
  17.   // Start UDP Server
  18.   sock := fpsocket(AF_INET, SOCK_DGRAM, 0);
  19.   ServerAddr.sin_family:= AF_INET;
  20.   ServerAddr.sin_addr := StrToNetAddr('127.0.0.1'); // server IP
  21.   ServerAddr.sin_port := 531; // server port
  22.   fpbind(sock, @ServerAddr, SizeOf(ServerAddr));
  23.   // Receive Data
  24.   SetLength(buff, UDPPackLen);
  25.   new(FromAddr);
  26.   new(FromAddrLen);
  27.   try
  28.     FromAddrLen^ := SizeOf(FromAddr^);
  29.     MessageSize := fprecvfrom(sock, @buff[1], Length(buff), 0, psockaddr(FromAddr), FromAddrLen);
  30.     WriteLn('err: ', socketerror);
  31.     SetLength(buff, MessageSize);
  32.     ClientAddr := NetAddrToStr(FromAddr^.sin_addr);
  33.     ClientPort := NToHs(FromAddr^.sin_port);
  34.   finally
  35.     Dispose(FromAddr);
  36.     Dispose(FromAddrLen);
  37.   end;
  38.   WriteLn(buff);
  39.   ReadLn;
  40. end.
  41.      


Of course the IP needs to be changed (I don't have IP 1.1.1.2)

PS: @TE are you shure you have IP 1.1.1.2, because as far as I know the 1.1.1.x IP range is owned by Cloudflare, who host their infrastructure their (as low ip numbers are a few nanoseconds faster than high ones in switching, to give them more performance for their CDN services)

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: cannot receive messages; udp server with lnet
« Reply #44 on: July 03, 2022, 11:42:18 am »
@Warfley. I didn't get a 10022 but a 10014 error with the fprecvfrom.

To solve this I didn't need to create FromAddr but could just leave it on the stack.
But you DO need to provide the correct FromAddrLen for it.
(And that was missing from the original code)

So here my code with fprecvfrom (with error checking).

Code: Pascal  [Select][+][-]
  1. program Receiver;
  2. uses
  3.   SysUtils, crt, sockets;
  4. const
  5.   UDPPackLen = 512;
  6. var
  7.   sock: Tsocket;
  8.   buff: array[0..UDPPackLen - 1] of char;
  9.   ServerAddr: sockaddr_in;
  10.   FromAddr: sockaddr_in;
  11.   FromAddrLen: Integer;
  12.   MessageSize: SizeInt;
  13.   outp: string;
  14. begin
  15.   sock := fpsocket(AF_INET, SOCK_DGRAM, 0);
  16.   assert(sock <> -1);
  17.   ServerAddr.sin_family := AF_INET;
  18.   ServerAddr.sin_addr := StrToNetAddr('192.168.2.11'); // server IP
  19.   ServerAddr.sin_port := htons(1234); // server port
  20.   if fpbind(sock, @ServerAddr, SizeOf(ServerAddr)) = 0 then
  21.   begin
  22.     repeat
  23.       FromAddrLen := SizeOf(FromAddr);
  24.       MessageSize := fprecvfrom(sock, @buff, Length(buff), 0, @FromAddr, @FromAddrLen);
  25.       if MessageSize = -1 then
  26.       begin
  27.         writeln(socketError);
  28.       end
  29.       else
  30.       begin
  31.         SetString(outp, pansichar(@buff[0]), 8);
  32.         writeln('Received: ' + outp + ' ' + NetAddrToStr(FromAddr.sin_addr));
  33.       end;
  34.       sleep(100);
  35.     until False;
  36.   end
  37.   else
  38.   begin
  39.     writeln(socketError);
  40.     readln;
  41.   end;
  42. end.

Quote
Received: 11:46:49 192.168.2.11
Received: 11:46:49 192.168.2.11
Received: 11:46:49 192.168.2.11
Received: 11:46:49 192.168.2.11
Received: 11:46:50 192.168.2.11
Received: 11:46:50 192.168.2.11
Received: 11:46:50 192.168.2.11
Received: 11:46:50 192.168.2.11
Received: 11:46:50 192.168.2.11
Received: 11:46:50 192.168.2.11
Received: 11:46:50 192.168.2.11
Received: 11:46:51 192.168.2.11
Received: 11:46:51 192.168.2.11
Received: 11:46:51 192.168.2.11
Received: 11:46:51 192.168.2.11
Received: 11:46:51 192.168.2.11
Received: 11:46:51 192.168.2.11
Received: 11:46:51 192.168.2.11
Received: 11:46:51 192.168.2.11

Edit:

Changing your code back to local variables it also works fine as long as you set FromAddrLen.
The moment you remove line 23 you'll get a 10014.
I think in this code the local variables are already always correctly aligned.
You do have a point that they could be misaligned but that's not the case here.

Code: Pascal  [Select][+][-]
  1. uses
  2.   sockets;
  3. const
  4.   UDPPackLen = 512;
  5. var
  6.   sock: Tsocket;
  7.   buff: String;
  8.   ServerAddr: sockaddr_in;
  9.   FromAddr: sockaddr_in;
  10.   FromAddrLen: Integer;
  11.   ClientAddr: String;
  12.   ClientPort: Word;
  13.   MessageSize: SizeInt;
  14. begin
  15.   // Start UDP Server
  16.   sock := fpsocket(AF_INET, SOCK_DGRAM, 0);
  17.   ServerAddr.sin_family:= AF_INET;
  18.   ServerAddr.sin_addr := StrToNetAddr('192.168.2.11'); // server IP
  19.   ServerAddr.sin_port := htons(1234); // server port
  20.   fpbind(sock, @ServerAddr, SizeOf(ServerAddr));
  21.   // Receive Data
  22.   SetLength(buff, UDPPackLen);
  23.   FromAddrLen := SizeOf(FromAddr);
  24.   MessageSize := fprecvfrom(sock, @buff[1], Length(buff), 0, @FromAddr, @FromAddrLen);
  25.   WriteLn('err: ', socketerror);
  26.   SetLength(buff, MessageSize);
  27.   ClientAddr := NetAddrToStr(FromAddr.sin_addr);
  28.   ClientPort := NToHs(FromAddr.sin_port);
  29.   WriteLn(buff);
  30.   ReadLn;
  31. end.

Quote
err: 0
11:56:52

« Last Edit: July 03, 2022, 11:57:04 am by rvk »

 

TinyPortal © 2005-2018