newLISP Fan Club

Forum => newLISP in the real world => Topic started by: newdep on July 28, 2004, 11:06:30 AM

Title: Problem with UDP
Post by: newdep on July 28, 2004, 11:06:30 AM
Hello Lutz,



Well i came to the status on where im porting some udp tools to newlisp and im running in to a problem...



The net-send-udp and net-receive-udp are actualy oke but not 100% according to the "protocol" ;-)



What is the case? ->



If an UDP packet is send to the remote it sends with it the source port, the remote server will reply to that source port to be able to communicate.

The newlisp  TCP stack is implemented that way, but the UDP stack not.





So what is missing? ->



Actualy the udp Stack needs the same behaviour as the TCP stack, to

be able to communicate towards a server on the current sessions and that

is a complete protocol.



It is a matter of Async communication the same as TCP works. Every UDP

sessions needs to have a (net-sessions-udp) too.



Also every UDP sessions must be able to grab the remote port , that is a

(net-peer 16)  for UDP that return the remote ip and port...



I hope you are able to rewrite/change the net-send-udp & net-receive-udp because the current implementation has its limits now.



I think its not a big rewrite, but you know your code better that anyone, I hope you consider the above... :)



the impact would be on:

(net-send-udp)

(net-receive-udp)

(net-sessions) -> (net-sessions-udp)

(net-peer)

(net-local)

(net-peek) "probably wont work on udp, not sure anymore"

(net-select)



If the above it changed you will have a fully UDP async communication way,

the same as TCP works, accept for the network-Timeout in UDP which is buildin into the (net-receive-udp) already OR build be used inside (net-select) !!!



Keep on lisping..

Regards, Norman
Title:
Post by: Lutz on July 28, 2004, 01:01:12 PM
By definition the UDP (User Datagram Protocol) does not have any sender/receiver handshakig protocol like Tcp does. The send goes into "empty space" and if nobody is listening on the receiving port of the receipient addrress or ip broadcast-space, the packet is lost.



For this reason there is no peek or select for pending bytes to read by UDP. If nobody is listening on the receiving end the packed goes into never-never land.



A UDP packed contains (optional no implemented by all OSs) the port number of the sender. It is available on Windows, Linux and BSD and it could be returned theoretically with the remote ip address on reception. But this port numer is deliberately chosen by the sender. On Linux it seems to be 32768 (hex 8000) most of the time, but on BSD it is jumping around and on Windows counting up starting with some deliberate value. So there is not much sense in returning it to the user, because it might not be available the next moment.



UDP is meant to be a very low level protocol and fast for all of the above reasons. You have to implement any kind of handshaking your self as part of the data you send, or use TCP right away.



Lutz
Title:
Post by: newdep on July 28, 2004, 01:21:14 PM
Hello Lutz,



Yes your completly right on UDP..



Still making client-server independent communication possible there

should be a way for the (net-receive-udp) to know what the source ip & port is.



a (net-peer) on udp could return this. And a (net-receive-udp)

could be provided with a return of the source port?

or perhaps a (net-peer-udp) ?





If the above is possible ,(even net-select would be great here, still a next step)

then the UDP implementation is more complete and able to communicate independent.



Indeed the UDP protocol behavior stays the same but the functions in newlisp

related to UDP would be far more flexible.



I.e.



Currently im unable to setup a UDP listener because im not sure what

the local port was my (net-send-udp) send the packet on, so i cant listen

localy on the port for incoming data. protocols like tftp and Some Game protocols do so..



Regards, Norman
Title:
Post by: Lutz on July 28, 2004, 02:14:26 PM
The source ip is contained in the list net-receive-udp returns as the second field. When you talk bag to the sender you use a so called "well known" port which is agreed upon prior. Normally this is a pair one listen port for the client and another listen port for the sender.



The sender specifies the address and port of the receiver is does not (cannot) specify the outgoing port, which is picked delieberately by the lower level socket routines. The receiver listens on that port targeted by the sender and knows the ip-address where a packet is coming from. The receiver then sends back a message on the "well known'' agreed upon port where previous sender now is listening on.



Again there is no select, net-receive-udp listens and immedeately returns the UDP packet when it arrives.



A net-peer is not necessary because you know already the address where a packet comes from, from the list returned by net-receive-udp.



The outgoing port used by net-send-udp is picked by the socket implementation of the OS and there is no way to specify those. You can only specify the port you are sending to.



The port targeted by the sender is agreed upon prior in the higher level protocol you are using those ports are kneown as "well known ports" and are listed in the /etc/services table. You can use net-service to query them, i.e.:



(net-service "domain" "udp") = 53



Lutz
Title:
Post by: newdep on July 28, 2004, 02:51:38 PM
Hello Lutz,



Yes we are talking about the same issue..let me go one step further...



if server always send back to the client-source-port then the following

will never work in newlisp for the client to receive the data from the server ->



client - > (net-send-udp "127.0.0.1" 2222 "im going back" )

client - > (net-receive-udp  ?????? 512 )

server -> (net-send-udp "127.0.0.1" "remote-source-port" "im going back" )



how can (net-receive-udp) know what its local port was?



Anyway.. i tested in my C code and it works nicely... If the OS does not

provide a source port in de Datagram (because its optional indeed) then

its simply "0" (and the OS needs a fixup ;-)



I hope you think about it with a nice cold beer ;-)



Regards, Norman.
Title:
Post by: pjot on July 28, 2004, 03:06:56 PM
One night away from holidays... but still hacking. Actually I am implementing the UDP protocol for the GTK-server. I've got it running with the following GNU AWK script:



-------------------

BEGIN{

system("gtk-server udp localhost:50000 &")

# Wait for the server to initialize

pause(1)

# Setup UDP socket to server

GTK = "/inet/udp/0/localhost/50000"

# Now define the GUI

print "gtk_init(NULL, NULL)" |& GTK; GTK |& getline

print "gtk_window_new(0)" |& GTK; GTK |& getline WINDOW

....etc

-------------------



However, with newLisp I have to wait for a UDP packet first, before I can send something to the server (see documentation example with "net-receive-udp").  I wonder why this is the case with newLisp. Why is it not possible to send to a UDP port right away?



If I do this anyway, the "net-receive-udp" command produces a NIL.



Is there a way to get around this?



Peter
Title:
Post by: newdep on July 28, 2004, 03:18:42 PM
Hiya Pjot,



with UDP you can send whatever you want, but the server needs to

be listening to be able to get it..With newlisp you can send! but you cannot

wait for data at the same time, that is because its not async. :-)





PS: its a coincidence that we both work on a UDP problem Lutz ;-)



Norman.
Title:
Post by: newdep on July 28, 2004, 03:26:20 PM
Pjot,



Yes if you are using th Gtk-server to listen and to write on 1 port then your client

on the SAME machine will fail, because you cannot have 2 server on 1 machien running with the same listening port.



Actualy that is my point too (indirectly), see above..



Hope Lutz likes beer ;-)



Regards, Norman.
Title:
Post by: pjot on July 28, 2004, 03:33:27 PM
Actually it is very easy. The GTK-server acts as UDP server, waiting for incoming packets. As soon as the UDP server receives something, it will reply. Then it returns to wait state again. BUT: this all happens on the same port. The port is determined by the client script, so the UDP-server will know to which port it has to send it's packets back.



It is almost like TCP, with the difference that it is UDP... ;-) Again, this is how the AWK demo works, so I know this works... Cheers!
Title:
Post by: newdep on July 28, 2004, 03:35:15 PM
Ofcaurse it works ;-)



But i think we need to buy a 6-pack for Lutz first :-)
Title:
Post by: pjot on July 28, 2004, 03:36:13 PM
Funny we work on UDP at the same time... let's buy a 6-pack Belgian beer (10%)... ;-)
Title:
Post by: Lutz on July 28, 2004, 03:59:50 PM
The Belgian would be fine, but the dark one please! ;-)



somehow still I don't get what you guys are up to? If you send a packet with



(net-send-udp receiver-ip receiver-listen-port message)



you have the receiver at receiver port doing:



(net-receive-udp receiver-listen-port max-bytes) => (sender-ip sender-message)





There is no such thing as:



(net-send-udp receiver-ip receiver-listen-port port-where-i-will-listen-for-your-answer message)



sender would have to make port-where-i-will-listen-for-your-answer part of the message itself. Because when you set up your socket for sending you can only specify the target port:



dest_sin.sin_port = htons((u_short)remotePort); /* the target/receiver port */

dest_sin.sin_family = AF_INET;



bytesSent = sendto(sock, buffer, size, NO_FLAGS_SET,

        (struct sockaddr *)&dest_sin, sizeof(dest_sin));



Perhaps if you explain me what you are doing in 'C' I can understand?



Lutz
Title:
Post by: pjot on July 28, 2004, 04:55:44 PM
In my situation, the newLisp script acts as a client, while the GTK-server is the UDP server. So there is an interaction between newLisp and C.



OK here my beta version with UDP (just the mainloop):



------------------------

while (1){

   if ((numbytes=recvfrom(sockfd, buf, MAX_LEN - 1, 0, (struct sockaddr *)&their_addr, &addr_len)) > 0) {



      /* Terminate incoming string */

      buf[numbytes] = '';



      /* Only determine values when empty */

      if (se == NULL) {

         se = gethostbyname(inet_ntoa(their_addr.sin_addr));

         their_addr.sin_family = AF_INET;      /* host byte order */

         their_addr.sin_port = htons((long)atol(port));  /* short, network byte order */

         their_addr.sin_addr = *((struct in_addr *)se->h_addr);

         memset(&(my_addr.sin_zero), '', 8);     /* zero the rest of the struct */

      }



      <do_something_with_incoming: buf[], send back pointer: *retstr>



      /* Add newline to returned string */

      strcat(retstr, "n");



      /* Now send the result back to the socket */

      if ((numbytes=sendto(sockfd, retstr, strlen(retstr), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) {

         Print_Error(2, "Could not send DATAGRAM packet", errno);

      }

   }

   else Print_Error(2, "Could not receive DATAGRAM packet", errno);

}

------------------------



As you can see, I determine the destination port from the port given as argument ('port' is one of the arguments to the GTK-server binary).



I just compiled my beta version with GCC and MinGW, this works. Tested UDP with Rebol in Windows, and the GUI came up.



So the idea is:



loop

client-script: send-udp port

server: receive-udp port

server: send-udp port

client-script: receive-udp port

until callback



The 'port' is in all the lines the same port. With newLisp however, it seems I have to do the following:



client-script: receive-udp port

loop

client-script: send-udp port

server: receive-udp port

server: send-udp port

client-script: receive-udp port

until callback



Now, why do I have to wait for a UDP packet first? Since if I do not, the client script will receive a NIL.



Maybe I am not having the same problem as Norman here; again, I just want to know why my newLisp client script has to wait for a UDP-packet first?
Title:
Post by: Lutz on July 28, 2004, 06:07:56 PM
Ok, now I see what is going on:



In your 'C' example the server receives on a aocket and immedeately sends back the replay on the same socket. You



keep the same socket open like in a TCP client/server session where the listener send back on the connected socket.



In newLISP the net-send-udp closes the socket after sending and will not try to receive back on it after response.



Your example:



loop

client-script: send-udp port

server: receive-udp port

server: send-udp port

client-script: receive-udp port

until callback



Actually works with newLISP if both client and server are newLISP. If one of them is GTK-server then



GTK-server tries to send back on the socket wher it received, but that connection is already closed. That is



fundamentally a very different thing.



In newLISP/UDP sockets are immedeately closed on both sides:



net-send-ip:

(1)create socket,

(2)use it to send to receiver address and port,

(3) close socket.



net-receive-udp:

(1)create socket

(2)listen on socket

(3)read udp packet on socket

(4)socket



The reason for this implenation is that UDP was primarily meant to be a protocol with no inherent handshaking, i.e.



when you do a syslog(), you just fire away your log message without waiting for anything back.



Of course you can work it the way you do, but I think than you should do Tcp/Ip. I am not familiar with the Gaming



usage of UDP perhaps the method you are describing is the way is the way they work UDP? The newLISP implementaion



is targeted towards controlling hardware over a network (i.e. video equipment), where the sending of a UDP packet



and it's reception is the complete transaction and anything else happens on a higher level in an application



protocol.



But there may be a solution! The net-connect function already has an undocumented additional "udp" option and I



could add one to net-listen too and then you could work this way:



server:

(net-listen port local-ip "udp") => socket

(while (not (net-select ...) ...)

(net-receive socket)

(net-send socket)



client:

(net-connect port remote-ip "udp") => socket

(net-send socket message)



etc.



So the idea is to work with normal net-send and net-receive but open the sockets for UDP with listen and connect. (the listen would only make the UDP socket not really 'listen' like a stream socket)





Lutz
Title:
Post by: pjot on July 29, 2004, 02:14:07 AM
Hi Lutz,



Good news! Your tip works. Right now, the newLisp script with UDP looks like:



-----------------------

# Define communication function

(define (gtk soc str)

(net-send soc str)

(net-receive soc 'tmp 16)

tmp)



# Start the gtk-server

(process "gtk-server udp localhost:50000")

(sleep 1000)



# Connect to the GTK-server

(set 'socket (net-connect "localhost" 50000 "udp"))



# Define GUI

(set 'tmp (gtk socket "gtk_init(NULL, NULL)"))

(set 'win (gtk socket "gtk_window_new(0)"))

.....etc

-----------------------



This works exactly as expected.



It will take some time before the UDP version of the GTK-server will be released (me being on holidays) but newLisp will be a client language supporting it.



Thank you!



Peter
Title:
Post by: newdep on July 29, 2004, 02:51:16 AM
Hello Lutz,



Yes, (net-connect) works that way indeed. What is needed extra

is the (net-listen) on UDP and the solotion is made. :-)



below is exactly what  I searched... Now the (net-listen) enhancement would

be great.. Can (net-select) be used this way too ?



> (net-connect "127.0.0.1" 54000 "udp")

300

> (net-local 300)

("127.0.0.1" 1224)



Regards and thanks for the thoughts :-)



Norman.
Title:
Post by: Lutz on July 29, 2004, 04:25:08 AM
net-select, net-peer, net-local and net-peek will not need the udp option, the socket receives the datagram or stream attribute during creation, after that it is just a socket and can be treated with all other functions in a normal way.



Lutz
Title:
Post by: newdep on July 29, 2004, 05:31:29 AM
That is great Lutz, so actualy the adjustment for (net-listen) is left?



Very nice...!
Title:
Post by: Lutz on July 29, 2004, 05:39:27 AM
Yes, I am leaving home now, but you get it tonight.



Lutz
Title:
Post by: newdep on August 01, 2004, 11:59:47 AM
Hello Lutz,



version linux 8.0.16



Using the (net-send) after opening the udp sessions to the remote (not a newlisp daemon) with a (net-connect sock "ip" "udp") the connection is directly dropped localy...actualy using newlisp <> newlisp (net-send) works fine.. Is the expectation different using none newlisp <> newlisp communication?





Secondly the server site, how to grab the remote peer? -->



> (set 'listen (net-listen 5555 "" "udp"))

5

> (net-peek listen)

0

*** remote client send "hello" with (net-send)

> (net-peek listen)

5

> (net-peer listen)

nil  <--- Howto pickup remote peer port in a different way?

> (net-sessions)

()

>



Thirdly.. i think you see it already ;-) the (net-sessions) is not

updated for the "udp" trick...

Not sure if you want to implant this into the core?



 



Regards,

Norman.
Title:
Post by: Lutz on August 01, 2004, 07:03:41 PM
The missing socket in the 'net-sessions' for 'net-listen' with "udp" option was an oversight and is quick to fix.



The other stuff, I have to look into it a little bit deeper. UDP with 'C' listen(), receive() and connect(), send() is something normally not done. What is used mostly with UDP is using the 'C' sendto() and revvfrom() functions. This is the way 'net-send-udp' and 'net-receive-udp' work, and it looks like getpeername() does not work on SOCK_DGRAM sockets. There is very little about all this found in books and on the internet, I will experiment and find out more about it tomorrow.



Lutz
Title:
Post by: newdep on August 02, 2004, 04:42:49 AM
No hurries...Take your time...:-)
Title:
Post by: newdep on August 02, 2004, 11:02:03 AM
Hi Lutz,



Yes sendto is often used without the connect function called befor but send

can be used also and can only work when connect is used to open the session

first.  I think this is what you already do with the current "udp" trick.. Enhancing the "udp" functionality could take a little rewrite but is generaly

the same as for tcp accept that you need an extra catch on error...



Regards, Norman.
Title:
Post by: Lutz on August 02, 2004, 12:03:51 PM
Yes, I am just about to upload 8.1.0-rc1 which gets the asynchrounous UDP stuff working.



In UDP mode sockets do not contain the peer information about ip-address and port, they are part of the UDP-packet itself.



I added two new functions:



(net-receive-from socket maxsize) => (message ip-no port)



and



(net-send-to ip-no port message socket)



also (net-receive-udp ...) now returns also the sender port as last member in the list.



This is now how you set up asynchrounous UDP server/client



;===== server



(net-listen port ip-strr "udp") =>sock-no

(while (not (net-select sock-no "r" 100000)) (...))



(net-receive-from sock-no max-bytes) => (message ip-str port)



(net-sent-to ip-str port reply-msg sock-no)



; etc



;====== client



(net-connect server-ip server-port "udp") => sock-no



(net-send sock-no message)

;; or

(net-send-to server-ip server-port message sock-no)



;; poll for reply from server

(while (not (net-select sock-no "r" 100000) (...))



(net-receive sock-no max-bytes)

;; or

(net-receive-from sock-no max-bytes



; etc





Note that on the server 'net-receive-from' and 'net-send-to' are critical because the listen socket has no clue about the remote address.



On the client side both can be used because the connect binds the remote address to the socket.





Lutz
Title:
Post by: newdep on August 02, 2004, 01:00:13 PM
You are going like the wind!

And a new release candidate And udp enhancement......:-)







Its already released i see..pfffffffff...
Title:
Post by: Lutz on August 02, 2004, 01:07:12 PM
Actually it was not much work, I just had to split net-send-udp and net-receive-udp in versions with and without creating and closing the socket. What took time was testing it and writing the documentation :-)



lutz
Title:
Post by: newdep on August 02, 2004, 01:18:05 PM
Hi Lutz,



Just out of curriosity :), why did you chose to create 2 new functions

and not create more options with existing ones?



Its just a slight thought that (net-send-to) and (net-send-udp) could have

been mixed (because net-send-udp creates a real seperation in the newlisp network functions and is very clear to the user, while i think it could confuse the user now there are 2 ways to goto Rome ;-), while just the differance in variables in the function would create the differance in behaviour...





i.e --->



(net-send-udp str-remotehost int-remoteport str-buffer [bool])

and

(net-send-to str-remotehost int-remoteport str-buffer int-socket)



only differ [bool] or int-socket so it could become -->



(net-send-udp str-remotehost int-remoteport str-buffer [int-socket] or [bool] or [ nothing ])







and for --->



(net-receive-udp int-port int-maxsize [int-microsec][str-addr-if])

and

(net-receive-from int-socket int-max-size)



differ the amount of variables and could become -->



(net-receive-udp [ int-socket int-max-size ]

                        or

                        [ int-port int-maxsize [int-microsec][str-addr-if] ])





Its just a personal taste but i like the compacked amount

of functions newlisp has and makes it with the enhancement in

the manual more logical?





What do you think?





Regards, Norman.
Title:
Post by: Lutz on August 02, 2004, 02:03:41 PM
I thought about this too and internally there are really only two functions (which take socket creation/close options), but then I realized that sendto() and recvfrom() can also be used for non UDP communications, following code works perfectly:



=== SERVER

> (net-listen 1234)

1984

> (net-accept 1984)

1976

> (net-receive-from 1976 20)

("hello" "0.0.0.0" 0)   ;; shows 0.0.0.0 for default adapter

>



=== CLIENT



> (net-connect "127.0.0.1" 1234)

1956

> (net-send-to "127.0.0.1" 1234 "hello" 1956)

5



In fact in this scenario you can mix match net-send-to/net-send and net-receive-from/net-receive to your liking. This is TCP communications not UDP. Note that at the server the sender port comes as a 0,  because of TCP protocol this field is not used. Using the new functions might be faster when on small data sizes in TCP (haven't measured it yet).  For this reason I thought it was better to show the user two pairs of functions to make the difference visible.



Lutz
Title:
Post by: newdep on August 02, 2004, 02:29:55 PM
Hello Lutz,



Yes it makes good sence and is flexible also but its also double syntaxing

for the use of tcp (the socket and the remote ip .port). Indeed a mix match position...



For tcp most people would use the way of setup a connection and then

send data to that socket/bind.. actualy with the (net-send-to) it has only

doubled the variables..for UDP its more logical because of the protocol.



It could be a fraction quicker using (net-send-to) under tcp but thats

purly internaly in newlisp and your creating a tcp alike udp ;-)



For the conventional way of tcp communication i would always choose the

bind -> sendto <- recvfrom way, because you always want to know who is on the other end of the line.... On Udp where the protocol is not depending

on stability, variations are possible and everyone knows it while using...



You could ofcaurse bring the (net-send-to) and (net-receive-from) under in variables for (net-send) and (net-send-udp) thus keeping tcp and udp seperated... On the other hand a slight enhancement in the Manual that (net-send-to) and (net-receive-from) can be used with tcp too might do the

trick, so that you have 2 real new netowrk functions not just for udp.



Regards, Norman.
Title:
Post by: Lutz on August 02, 2004, 02:59:01 PM
Perhaps we need a whole new chapter in the users manual giving templates how to set up client/server code for both protocols.



By now many programmers are familiar with what you can do with TCP, but few know the importance of UDP. I ran into it when somebody asked for UDP to control video equipment and then I implemented net-send/receive-udp.



I wonder how you got involved with UDP, is it network gameing ?



What also would be great to have some 'Norman's 5-cent' stuff for UDP (innocent hint ;-))



Lutz
Title:
Post by: newdep on August 03, 2004, 05:21:03 AM
Hi Lutz,



Little testing on WINdows with version 8.1.0-Rc1...



Seems to be a problem with (net-receive-from), its not ctaching

anoything from the remote site. Only tested on Win2000 not on linux yet..



Example below, perhpas you see the issue?





**** SERVER



value expected in function net-listen : "127.0.0.1"



> (net-listen 5555 "127.0.0.1" "udp")

104

> (net-send-to "127.0.0.1" 5555 "testing" 104)

7

>







**** CLIENT



> (net-connect "127.0.0.1" 5555 "udp")

292

> (net-receive-from 292 512)

---- waiting and waiting...while server is already read sending...
Title:
Post by: Lutz on August 03, 2004, 06:33:37 AM
You are not sending to the correct port. The parameters you specify in net-send-to are those for the remote computer. You don't knows its port until your first 'net-receive-from'. Always the client has to initiate the conversation (in this case LINUX):



;=== SERVER

(net-listen 5555 "127.0.0.1" "udp") => 5 ; socket 5

5

(net-receive-from 5 20) => ("hello" "127.0.0.1" 32769)

(net-send-to "127.0.0.1" 32769 "hi there" 5)



;=== Client in a different shell on the same computer 127.0.0.1

(net-connect "127.0.0.1" 5555 "udp") => 6 ; socket 6

(net-send 6 "hello")

;; or (net-send-to "127.0.0.1" 5555 "hello" 6)



(net-receive 6 'buff 20)

;; or (net-receive-from 6 20) => ("hi there" "127.0.0.1" 5555)

buff => "hi there"



The SERVER has to make the first net-receive-from to get the senders port. The senders port, which in this case is 32769 is the port the client uses (picks automatically) when sending to the servers port 5555. Note that on the client side I can use both, net-send-to and net-send and net-receive and net-receive-from. The reason is that the client knows the remote port while the server does not know the remote port until the first net-receive-from.



Lutz
Title:
Post by: Lutz on August 03, 2004, 06:38:05 AM
You are not sending to the correct port. The parameters you specify in net-send-to are those for the remote computer. You don't knows its port until your first 'net-receive-from'. Always the client has to initiate the conversation (in this case LINUX):



;=== SERVER

(net-listen 5555 "127.0.0.1" "udp") => 5 ; socket 5

5

(net-receive-from 5 20) => ("hello" "127.0.0.1" 32769)

(net-send-to "127.0.0.1" 32769 "hi there" 5)



;=== Client in a different shell on the same computer 127.0.0.1

(net-connect "127.0.0.1" 5555 "udp") => 6 ; socket 6

(net-send 6 "hello")

;; or (net-send-to "127.0.0.1" 5555 "hello" 6)



(net-receive 6 'buff 20)

;; or (net-receive-from 6 20) => ("hi there" "127.0.0.1" 5555)

buff => "hi there"



The SERVER has to make the first net-receive-from to get the senders port. The senders port, which in this case is 32769 is the port the client uses (picks automatically) when sending to the servers port 5555. Note that on the client side I can use both, net-send-to and net-send and net-receive and net-receive-from. The reason is that the client knows the remote port while the server does not know the remote port until the first net-receive-from.



Lutz
Title:
Post by: Lutz on August 03, 2004, 09:55:30 AM
Here is a short example for UDP server/client communications, start the server first:



=== SERVER ===



#!/usr/bin/newlisp

(set 'socket (net-listen 1001 "" "udp"))
(println "server listening on port " 1001)
(while (not (net-error))
(set 'msg (net-receive-from socket 255))
(println "->" msg)
        (net-send-to (nth 1 msg) (nth 2 msg) (upper-case (first msg)) socket))

;; eof


=== CLIENT ===

#!/usr/bin/newlisp

(set 'socket (net-connect "127.0.0.1" 1001 "udp"))
(while (not (net-error))
(print "->")
(net-send socket (read-line))
(net-receive socket 'buff 255)
(println "=>" buff))

; eof


Lutz
Title:
Post by: newdep on August 03, 2004, 10:21:50 AM
Hello Lutz,



>Perhaps we need a whole new chapter in the users manual

> giving templates how to set up client/server code for both protocols.



Good idea...



>I wonder how you got involved with UDP, is it network gameing ?



Well.. no not directly, its a long story but actualy i just happen to be e network junky in languages. Its realy good that newlisp has good UDP support, as not many languages support UDP good or not at all.



>What also would be great to have some 'Norman's 5-cent' stuff for UDP >(innocent hint ;-))



Ooo yes somethings are upcoming, im very bussy this month but have two

nice projects for udp on my list, ill post them when ready... :-)



Thank for the explanation on the net-receive-from, I was out of way :)



Regards, Norman.
Title:
Post by: newdep on August 04, 2004, 02:51:12 PM
Hello Lutz,



Well amazingly I spend the last two days thinking what is wrong with the

UDP in newlisp communication. Well finaly i grabbed my good old sniffer and

started analizing the packets flying over the copper using my UDP newlisp client that was communicating towards a Remote UDP-server (not newlisp).



My client was unable to communicate, as i figured out after 4 hours thinking

that i was doing something wrong. But its seems my expectations from the

UDP implant where different then expected.



See my client communicates towards a remote UDP-server. This remote

UDP server listens for incoming sessions on a specific port. When data comes

in on that port it will start sending it own data to the connected client (which is the newlisp udp client) And now the trick !





The server listens on port : 1000 UDP



--> The client connect to server:1000 on UDP, source port 32222 desti: 1000

<-- server sends reply to client with source port:8888 desti port: 32222

--> client is listening for data on remote-port source 1000, And here it goes wrong !!



Strickly when communicating on UDP the client server communication

goes trough source and destination frame from UDP based on addressing

from IP frame.



So eventualy when UDP communicates it communicates on source and

destinationport inside the UDP header. And that does not happen in newlisp.

Newlisp expects packets to come from the Serving-port (1000 in this example) as the UDP header contains the real source port newlisp is unable

to receive the data coming from the UDP server. That was my initial problem

i wrote here the first time...



Actualy newlisp should be able, when acting as a client i.e. (net-receive) in udp-mode to check the source port for every incoming packet

from the server and send back on that port with (net-send).

For the server-side its oke because it is sending to the right port but newlisp is currenlty listening on the serving-port instead on the port in the udp header...



I tried to configure it, but im unable to get newlisp to listen on incoming

data from an unknown source port...perhpas you have a hint ?



Well its a RFC issue and I hope you understand my story above...



My question, Are you able to do something about it perphaps ? ;-)



Regards, Norman.
Title:
Post by: Lutz on August 04, 2004, 03:23:39 PM
>>>

Actualy newlisp should be able, when acting as a client i.e. (net-receive) in

udp-mode to check the source port for every incoming packet

>>>



yes, use net-receive-from on the client to find out the port the server used to send.



--> The client connect to server:1000 on UDP, source port 32222 desti: 1000

correct

<-- server sends reply to client with source port:8888 desti port: 32222

correct



--> client is listening for data on remote-port source 1000, And here it goes wrong !!



No, there is not such thing as listening on "remote-port source 1000"



The sender never defines it's senders port, only the taget receiving port.



The client listens on the socket it used to send its first message to the server. The server then targets the port of the client it receives in the udp message. See my client/server example from a previous message.



Perhaps you can give me some 'C' code to see how your clients carries on communivations with a newLISP udp server.



You client should send to the 'well-known' (RFC-lingo) port of the newLISP server. The newLISP server will send back to port it reads in the client's UDP package. The client just listens on the same socket it originally used to send out the first packet.



Lutz



ps: the client should never have the need to use net-receive-from, becuase he knows the remote server listen port, when he (the client) initiated the conversation. The client just keeps listening on the sock first used to contact the serve (see the 'C' code of my next post)
Title:
Post by: Lutz on August 04, 2004, 05:21:37 PM
Norman, I made a little 'C' program for you to show how to talk to a newLISP UDP server here: http://www.newlisp.org/udp-client.txt



the newLISP udp-server.lsp is here: http://www.newlisp.org/udp-server.txt



The lisp part is the same as posted in this thread previously together with the newLISP client.



Start the udp-server.lsp first then use the 'C' client:



    udp-client "127.0.0.1" 1001



When you enter something at the client it gets echoed as uppercase.



You can compile the udp-client.c in two flavors: using sento() / recvfrom() or using send() / recv(). Both work well.



The difference is that in sendto()/recvfom() address info is part of the data packet in the  "stuct sockaddr_in" 'C' structure while using send()/revv() this structure is bound to the socket by connect().



Lutz
Title:
Post by: newdep on August 05, 2004, 12:33:50 AM
Hi Lutz,



Driving for two hours this morning, having a lot of time to think during traffic jams...i think I have found a trick to workaround my problem.

Ill see if it works. Ill test your C programs too.. Ill get back to you..



Thanks..Norman.
Title:
Post by: newdep on August 05, 2004, 11:47:46 AM
Hi lutz,



Oke ill explain it once more with an example,

The server is a NONE newlisp program.

So only focus on the client behaviour :-)





Options #1 communication on UDP -->

In this example (net-receive) on the CLIENT side works fine.



*** server listens on port 54054



--> client UDP packet to server (SRC: 32222 | DST: 54054 )

<-- server UDP packet to client (SRC: 54054 | DST: 32222 )

--> client accepts packet.





Options #2 communication on UDP -->

In this example (net-receive) on the CLIENT does not work.



*** server listens on port 54054



--> client UDP packet to server (SRC: 32222 | DST: 54054 )

<-- server UDP packet to client (SRC: 444444 | DST: 32222 )

--> client waits....waits....waits...waits..



The server initiates its Own session to send a reply on what the

client has send. The differance is the SRC-port from the server.

This port is unknown by the newlisp sockets and thus a (net-receive) or (net-receive-from) or (net-receive-udp) always in a wait-forever...



Looks like net-receive does check on source port but does not dynamicly

change the socket options of that sessions internaly.



I agree with you if you say, that way of server communication is odd.

But it is actualy the same as tcp works.



I hope its a little more clear and probably you will tell me to take a hike

and have a beer somewhere on the hill ;-) Just tell me what you think of it...





PS: actualy i had this morning a workaround on windows for the problem.

And that is to initiate a (net-listen) on the (net-local) of the client after sending the data to the server and befor receiving data from the server.

Not realy charming because its a second sessions but i was able to receive data from the server. And currently im unable to reproduce this under linux...odd..



Regards, Norman
Title:
Post by: newdep on August 05, 2004, 12:20:57 PM
So indeed the solution is as follows (works on both linux / Windows) ->



(set 'remote (net-connect "remote" 54054 "udp") )

(net-send remote "00010203")

(set 'C (net-local remote))

(close remote)

(net-listen C "" "udp")

(net-receive C 'buff 1024)

(net-send C "05060708")



etc..voila.. it works..



Question remains. -> why this way?

This is the result of "initial" none-static port communication.



Anyway..workaround available , but not according logic and

not very usefull in client UDP communication, client becomes

server this way ;-)



Regards, Norman.
Title:
Post by: Lutz on August 05, 2004, 03:44:56 PM
You should be able to to do a (net-receive remote maxbytes) without having to create a new socket.



What I suspect is, that your server is closing the socket after sending the last response, which is the 'normal' way to do UDP communications, and the way 'net-send-udp' and 'net-receive-udp' work.



We know that that client 'C' <> newlisp-server non-blocking works and we also know that server 'C' <> newlisp-client works from Peters experiments with GTK-server.



I could make an other example in 'C' for 'C'-server with newlisp-client, but I think that this is redundant as Peter has done it with GTK-server already.



Can you get hold of the server code you are trying to talk to?



Lutz
Title:
Post by: newdep on August 06, 2004, 02:43:59 PM
*** up and running *** :-)
Title:
Post by: Lutz on August 06, 2004, 03:39:17 PM
After some offline experiments together with Norman on the UDP stuff here a better way, how to code a newLISP UDP client http://www.newlisp.org/udp-comm.txt  This will also be included in code examples and the manual.



I also suggest that Peter changes to this method in the GTK-server example, although the old method seemed to work too. (in any case the capability of "udp" in  net-connect will stay)



Using (net-listen ... "udp") on both sides guarantees that the local socket is always named (bound to local address:por) correctly.



Lutz
Title:
Post by: pjot on August 12, 2004, 10:24:24 AM
Done. I have only tested this in Linux now, later this week I'll have the opportunity to test with Windows.



http://www.gtk-server.org/demo-udp.lsp.txt



Peter
Title:
Post by: pjot on August 12, 2004, 11:03:37 AM
BUT: it seems that the original net-receive-udp timeout does not work anymore.



(net-receive-udp 57000 128 50000 "127.0.0.1")



If I use this string in the newLisp prompt, newLisp waits endless. But it should timeout after 50000 microseconds. Using newlisp 8.1.0.
Title:
Post by: HPW on August 12, 2004, 12:19:07 PM
Quote
BUT: it seems that the original net-receive-udp timeout does not work anymore.


I see the same when testing with the newLISP.DLL on windows.

It seems not to get back when the timeout is over.

Instead it makes the timeout when it get's a UDP-message.

Then it makes the pending timeout.
Title:
Post by: Lutz on August 12, 2004, 12:38:00 PM
I am not in the office right now but will check later this evening. There have been some changes in UDP stuff, but 8.10 is identical to 8.1.0-rc2 in this respect.



Lutz
Title:
Post by: Lutz on August 12, 2004, 04:17:28 PM
I found the problem, the feature got wiped out doing the other UDP additions. I will do a re-release on Friday with version 8.1.1



Lutz



PS: this will not contain the new install_home options, I want to go safe because of changes in newlisp-tk.tcl.
Title:
Post by: nigelbrown on August 12, 2004, 05:43:25 PM
Lutz,

Would you like to e-mail me the home_install makefiles and newlisp-tk.config.home to try out? I have a few live distros.

Regards

Nigel
Title:
Post by: Lutz on August 12, 2004, 06:00:24 PM
If you could test that the new install features on a few live distros, that would be great!



I have all your stuff integrated but did not want to risk anything for 8.1.1. There is also a small change in newlisp-tk.tcl, which I did not want to have exposed for this release. I have had too much trouble with directory and startup issues in newlisp-tk in the past.



I just put 8.1.1 with the UDP timeout fix in the development directory and want to put this in the release directory tomorrow.



I will do a 8.1.2 development release shortly after with the new make file features for the $HOME install.



Lutz
Title:
Post by: nigelbrown on August 12, 2004, 09:30:48 PM
I'll look out for it Lutz



Maybe you should consider using the even=stable odd=devel system

for the minor version number a la kernal etc

with 8.2 the next stable release and 8.2.1 etc bug fixes

and 8.3.z the devel series - or maybe that's going too far for newlisp?

It would more clearly split off the new testing stuff.

Nigel
Title:
Post by: pjot on August 13, 2004, 02:08:25 AM
Hi Lutz, I see your new 8.1.1 version, I will test it this evening.



Thanx,



Peter
Title:
Post by: HPW on August 13, 2004, 02:15:05 AM
8.1.1 works for me with the DLL-version.
Title:
Post by: pjot on August 13, 2004, 02:48:07 PM
Yes, the timeout works OK again. Thanks!
Title: Broadcast
Post by: newdep on August 13, 2004, 05:05:00 PM
Hello Lutz,



Actualy i ran into the fact that a (net-receive-udp) is the only option

under linux to receive a broadcast message. Where on windows also

a (net-listen...) (net-receive-from) works on receiving boradcasts....??

Could this be correct?



Regards, Norman/
Title:
Post by: Lutz on August 13, 2004, 05:36:58 PM
the underlying 'C' code is the same on both OS, but there seem to be differences how both OS implement the socket stack. I also observed, that on some OS the broadcast flag is unnecessary and just sending to the broadcast address is enough.



Lutz
Title:
Post by: pjot on August 14, 2004, 02:16:20 PM
Hi all,



Just to let you know, I created a simple UDP chat using GTK. Though fully functional, it's more like an advanced demonstration. Screenshots can be found here:



http://www.gtk-server.org/apps.html



The full source can be downloaded there as well.



--------------------



Features:



- Full GTK2.x

- Using scrolled text_view widget

- Memorizes last entered configuration

- Works on Linux and Win32 with same source code

- Uses encryption of the actual chat



Bugs, remarks, comments are welcome.



Peter.
Title:
Post by: Lutz on August 15, 2004, 07:43:08 AM
Thanks Peter, looks great! When I start chat.lsp it starts the gtk-server creates the main window and outlines the controls but then seems to wait for something. Is there a server application I have to start first?



Lutz
Title:
Post by: pjot on August 15, 2004, 01:34:26 PM
No, the chatprogram is server and client at the same time!



So, when somebody sends a UDP DGRAM to your IP address, it will be displayed by the chat program.



You have to specify the IP address in the upper entry, with a port. (If you do not specify a port, the default port 54000 is used.)



The IP address specifies the remote host, where you send your chat (DGRAM) to. The specified port however is BOTH the remote port AND ALSO the local port, where the chat program listens for incoming DGRAMS. So the port number should be the same on both sides, as well as the encryption string.



I hope you enjoy the chat!