Recent

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

prodingus

  • Jr. Member
  • **
  • Posts: 74
Re: cannot receive messages; udp server with lnet
« Reply #45 on: July 03, 2022, 06:22:27 pm »
Code: Pascal  [Select][+][-]
  1. program send_data_test;
  2. {$APPTYPE CONSOLE}
  3. uses
  4.         sysutils, crt, lnet;
  5. var
  6.         Sock:TLUDP;
  7.         i,j,k:integer;
  8.  
  9.  
  10. begin
  11.         i:=0;
  12.  
  13.  
  14.         Sock:= TLUdp.Create(nil);
  15.         Sock.connect('1.1.1.2', 1234);
  16.  
  17.  
  18.         repeat begin
  19.  
  20.                 sock.sendmessage(inttostr(i+5));
  21.                 i:=i+1;
  22.                 writeln(i,' ', inttostr(i+5));
  23.  
  24.                 sleep(10);
  25.  
  26.         end; until keypressed=true;
  27.  
  28.         readln;
  29.  
  30. end.

the client,


Code: Pascal  [Select][+][-]
  1. program sockets_1;
  2.  
  3. uses
  4.         sysutils, crt, sockets;
  5.  
  6. const
  7.   UDPPackLen = 512;
  8. var
  9.         i:integer;
  10.   sock: Tsocket;
  11.   buff: string;
  12.  
  13.   outp:string;
  14.  
  15.   ServerAddr: sockaddr_in;
  16.   FromAddr:  sockaddr_in;
  17.   FromAddrLen: Integer;
  18.   ClientAddr: String;
  19.   ClientPort: Word;
  20.   MessageSize: SizeInt;
  21. begin
  22.  
  23.     i:=0;
  24.         // Start UDP Server
  25.         sock := fpsocket(AF_INET, SOCK_DGRAM, 0);
  26.         ServerAddr.sin_family:= AF_INET;
  27.         ServerAddr.sin_addr := StrToNetAddr('1.1.1.2'); // server IP
  28.         ServerAddr.sin_port := htons(1234); // server port
  29.         fpbind(sock, @ServerAddr, SizeOf(ServerAddr));
  30.  
  31.         writeln(sock <> -1);
  32.         writeln(socketError);
  33.  
  34.         // Receive Data
  35.         SetLength(buff, UDPPackLen);
  36.         FromAddrLen := SizeOf(FromAddr);
  37.         writeln(socketError);
  38.  
  39.                 MessageSize := fprecvfrom(sock, @buff[1], Length(buff), 0, @FromAddr, @FromAddrLen);
  40.                 //WriteLn('err: ', socketerror);
  41.                 SetLength(buff, MessageSize);
  42.                 ClientAddr := NetAddrToStr(FromAddr.sin_addr);
  43.                 ClientPort := NToHs(FromAddr.sin_port);
  44.         repeat begin
  45.                 SetLength(buff, MessageSize);
  46.                 MessageSize := fprecvfrom(sock, @buff[1], Length(buff), 0, @FromAddr, @FromAddrLen);
  47.  
  48.                 i:=i+1;
  49.                 WriteLn(i,' ',buff);
  50.                 sleep(100);
  51.         end; until false;
  52.         ReadLn;
  53.  
  54.  
  55. end.
  56.  

the server.

The client sends with sleep(10) and the server receives (YES, its working!!!) with sleep(100).
The problem 1 is that the server keeps receiving even after I stop client, and 2 the received messages stop at 10 (displays only 1 and for 11+ displays nothing). The +5 was just for check, no other reason.
lazarus 1.6, FPC 3.0, SVN 51630.

MarkMLl

  • Hero Member
  • *****
  • Posts: 4751
Re: cannot receive messages; udp server with lnet
« Reply #46 on: July 03, 2022, 06:24:34 pm »
The problem 1 is that the server keeps receiving even after I stop client

What do you mean?

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

rvk

  • Hero Member
  • *****
  • Posts: 4819
Re: cannot receive messages; udp server with lnet
« Reply #47 on: July 03, 2022, 06:32:53 pm »
The client sends with sleep(10) and the server receives (YES, its working!!!) with sleep(100).
The problem 1 is that the server keeps receiving even after I stop client, and 2 the received messages stop at 10 (displays only 1 and for 11+ displays nothing). The +5 was just for check, no other reason.
1) UDP also has a buffer so it's usual you would end up with additional message if your sender is faster than the receiver.

2) You have a  SetLength(buff, MessageSize); on line 45. But MessageSize is the result of the previous fprecvfrom !!!
So the MessageSize could be 0. You need to do a SetLength(buff, UDPPackLen); before the fprecvfrom to make room for the string AND a SetLength(buff, MessageSize); to cut the buffer/string to the correct received size after the fprecvfrom.

So somthing like this:

Code: Pascal  [Select][+][-]
  1. i:=0;
  2. // Start UDP Server
  3. sock := fpsocket(AF_INET, SOCK_DGRAM, 0);
  4. ServerAddr.sin_family:= AF_INET;
  5. ServerAddr.sin_addr := StrToNetAddr('1.1.1.2'); // server IP
  6. ServerAddr.sin_port := htons(1234); // server port
  7. fpbind(sock, @ServerAddr, SizeOf(ServerAddr));
  8.  
  9. repeat
  10.   SetLength(buff, UDPPackLen);
  11.   MessageSize := fprecvfrom(sock, @buff[1], Length(buff), 0, @FromAddr, @FromAddrLen);
  12.   SetLength(buff, MessageSize);
  13.  
  14.   ClientAddr := NetAddrToStr(FromAddr.sin_addr);
  15.   ClientPort := NToHs(FromAddr.sin_port);
  16.  
  17.   i:=i+1;
  18.   WriteLn(i,' ',buff);
  19.   sleep(100);
  20. until false;

No need to do the first fprecvfrom you have above the repeat.
And no need to wrap the code inside repeat/until in begin/end.
« Last Edit: July 03, 2022, 06:36:45 pm by rvk »

MarkMLl

  • Hero Member
  • *****
  • Posts: 4751
Re: cannot receive messages; udp server with lnet
« Reply #48 on: July 03, 2022, 06:40:17 pm »
You need to do a SetLength(buff, UDPPackLen); before the fprecvfrom to make room for the string AND a SetLength(buff, MessageSize); to cut the buffer/string to the correct received size after the fprecvfrom.

As in my original example. Also I'd note that I've edited that to use AnsiString, lest any "extended ASCII" characters appear and cause confusion.

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

prodingus

  • Jr. Member
  • **
  • Posts: 74
Re: cannot receive messages; udp server with lnet
« Reply #49 on: July 03, 2022, 06:46:43 pm »
Quote
What do you mean?
The client sends fast and the server receives slower (seems to receive slower because of sleep(100)); as rvk said, its a buffer.

Quote
2) You have a  SetLength(buff, MessageSize); on line 45. But MessageSize is the result of the previous fprecvfrom !!!
So the MessageSize could be 0. You need to do a SetLength(buff, UDPPackLen); before the fprecvfrom to make room for the string AND a SetLength(buff, MessageSize); to cut the buffer/string to the correct received size after the fprecvfrom.

yes, that did the trick.

The thing with the buffer, does it have anything to do with synchronous/asynchronous? I thought that udp packets, if you don't receive them in time, you loose them.
« Last Edit: July 03, 2022, 06:51:25 pm by prodingus »
lazarus 1.6, FPC 3.0, SVN 51630.

rvk

  • Hero Member
  • *****
  • Posts: 4819
Re: cannot receive messages; udp server with lnet
« Reply #50 on: July 03, 2022, 06:55:58 pm »
The thing with the buffer, does it have anything to do with synchronous/asynchronous? I thought that udp packets, if you don't receive them in time, you loose them.
No. Buffering is normal. I'm not sure how large the buffer for udp socket is on Windows but there are also some other buffers at play. Buffer in the network adapter for example.

So, although UDP reception is not guaranteed, the reliabilty of receiving them can be quite high. Just make sure your reception is fast enough (or at least faster than your sending).

prodingus

  • Jr. Member
  • **
  • Posts: 74
Re: cannot receive messages; udp server with lnet
« Reply #51 on: July 03, 2022, 07:13:17 pm »
It seems that the communication is reliable, with one quirk: the last message is not received, althout the client seems to have send it judging from the client's output (must be the repeat loop?).

The problem with the buffer is this: I wanted to make the client send message 1 to the server, then when the server received the message 1, send a message 2 to client, and again when the client received the message 2 send a new message 3 to server and so on. A ping-pong as fast as the connection (hops, latency) can be (2 vms using their dedicated virtual adapter should be quite fast).
« Last Edit: July 03, 2022, 07:16:00 pm by prodingus »
lazarus 1.6, FPC 3.0, SVN 51630.

rvk

  • Hero Member
  • *****
  • Posts: 4819
Re: cannot receive messages; udp server with lnet
« Reply #52 on: July 03, 2022, 07:17:13 pm »
The problem with the buffer is this: I wanted to make the client send message 1 to the server, then when the server received the message 1, send a message 2 to client, and again when the client received the message 2 send a new message 3 to server and so on. A ping-pong as fast as the connection (hops, latency) can be (2 vms using their dedicated virtual adpater should be quite fast).
Then why are you using UDP and not TCP connection?

You can simulate it by sending an UDP message back and only send the next message when you get the ACK (acknowledgement) back but that will slow down things. A direct TCP connection seems much more appropriate for your description.

BTW. You increase the I after sending but before printing to screen so you actually didn't send that last printed number.

Warfley

  • Hero Member
  • *****
  • Posts: 910
Re: cannot receive messages; udp server with lnet
« Reply #53 on: July 03, 2022, 07:17:33 pm »
The problem 1 is that the server keeps receiving even after I stop client, and 2 the received messages stop at 10 (displays only 1 and for 11+ displays nothing). The +5 was just for check, no other reason.
That is the nature of UDP. UDP is connectionless, meaning you just receive datagrams, no matter from which client and what the client state is, and also it is unreliable, meaning that data can get lost.
If you want to know when the client disconnects, and you require reliable transmission, you shouldn't use UDP

prodingus

  • Jr. Member
  • **
  • Posts: 74
Re: cannot receive messages; udp server with lnet
« Reply #54 on: July 03, 2022, 07:24:32 pm »
Quote
Then why are you using UDP and not TCP connection?
I am going to try the ping-pong. I want to use udp instead of tcp because I want to have as low lag as possible. What I am going to do if a packet is lost is up to me to make or not a custom ack/resend.

Quote
ou can simulate it by sending an UDP message back and only send the next message when you get the ACK (acknowledgement) back but that will slow down things.
Does udp return ack by itself?

Quote
BTW. You increase the I after sending but before printing to screen so you actually didn't send that last printed number.
AGAIN, correct!!!

Quote
If you want to know when the client disconnects, and you require reliable transmission, you shouldn't use UDP

I don't mind that (at least yet).
lazarus 1.6, FPC 3.0, SVN 51630.

rvk

  • Hero Member
  • *****
  • Posts: 4819
Re: cannot receive messages; udp server with lnet
« Reply #55 on: July 03, 2022, 07:30:19 pm »
Does udp return ack by itself?
No, that's the whole point of UDP.
No return message and no guarantee someone receives the message.

The upside is that you can also send an UDP message to the whole network (broadcast) without knowing any of their IPs. Receivers can answer that they received it (via return UDP message or TCP connection request).




prodingus

  • Jr. Member
  • **
  • Posts: 74
Re: cannot receive messages; udp server with lnet
« Reply #56 on: July 03, 2022, 07:35:52 pm »
Quote
No, that's the whole point of UDP.
No return message and no guarantee someone receives the message.
That's what I thought, I missinterpreted what you wrote before.

Quote
The upside is that you can also send an UDP message to the whole network (broadcast) without knowing any of their IPs. Receivers can answer that they received it (via return UDP message or TCP connection request).
I am aware of that.

Back to the buffer thing, let's say I want the packets to be droped if the server does not receive them in time. How to do that?
lazarus 1.6, FPC 3.0, SVN 51630.

rvk

  • Hero Member
  • *****
  • Posts: 4819
Re: cannot receive messages; udp server with lnet
« Reply #57 on: July 03, 2022, 07:39:44 pm »
Back to the buffer thing, let's say I want the packets to be droped if the server does not receive them in time. How to do that?
Send a timestamp with the UDP message from the sender and ignore it on the receiving end if it's too old. That would mean that both computers need to be exact in timesettings.

So, what us your definition of "receive them in time" ?

prodingus

  • Jr. Member
  • **
  • Posts: 74
Re: cannot receive messages; udp server with lnet
« Reply #58 on: July 03, 2022, 07:47:37 pm »
Timestamp will add small latency to the program. Receive them in time = receive when the datagram has arrived at the destination and the program reads it. I might have wrong assumptions on how things work. I thought that a udp datagram arrives, if you read it fast, then good, else the packet is gone/replaced by the next one. I set the server to sleep(1000), I still received all the datagrams.
lazarus 1.6, FPC 3.0, SVN 51630.

Warfley

  • Hero Member
  • *****
  • Posts: 910
Re: cannot receive messages; udp server with lnet
« Reply #59 on: July 03, 2022, 07:52:13 pm »
There is more than just UDP and TCP, there are things in between
TCP is a reliable ordered stream of data. UDP is for transmitting unreliable unordered packages. There is also RDM (Reliable Delivered Messages), which sends acks and has therefore delivery guarantees, but does not guarantee order, or SEQPACKET (Sequenced Packet), which also ensures ordering and is like TCP also connection based, but unlike TCP it does not provide a stream of data but only single packets, and therefore is more lightweight. Depending on how much guarantees you need and also how much overhead they imply, they can be useful choices as in-between options.

 

TinyPortal © 2005-2018