:Class UDP ⍝ Class for Asynchronous UDP/IP Communication ⍝ List of methods: ⍝ SendReceive = Send the bytes and return the bytes received ⍝ Version 1.1 January 2016 ⍝ .Net assemblies: :Using :Using System.Net,System.dll :Using System.Net.Sockets,System.dll :Field Public udpObj :Field Public Type←'UDP' :Field Public _Retries←3 ⍝ Number of retries if no answer from remote host. :Field Public _PortTimeOut←250 ⍝ Time in milliseconds to Wait for a UdpClient that is not Active (Receiving Nothing). (⎕IO ⎕ML ⎕WX)←1 3 3 ⍝ System variables ∇ Init0 :Access Public :Implements Constructor ∇ ∇ r←SendReceive(bytes ip port);data;ipep;retries;task :Access Public ⍝ Send the bytes and return the bytes received ⍝ bytes = Bytes (as Numbers 0 to 255) to be Written to the Communication Port ⍝ ip = IP Address where to send the bytes in characters ('192.168.1.1') or numbers (192 168 1 1) ⍝ port = Port Number to send the bytes (0 - 65535) ⍝ ⍝ r[1] = 1 for Success, 0 for Failure ⍝ r[2] = Response if Success, Literal Error if Failure :Trap 0 ⍝ Prepare the IP adress: :If ' '=↑1↑0⍴ip ⍝ Characters ? ip←IPAddress.Parse(⊂,ip) ip←⎕NEW IPAddress(ip.Address) :Else ⍝ Numbers ip←⎕NEW IPAddress(⊂,ip) :EndIf ⍝ Prepare the IPEndPoint ipep←⎕NEW IPEndPoint(ip port) retries←_Retries ⍝ Loop until some data is received ⍝ or the number of retries is exceeded. :While retries>0 ⍝ Prepare the UdpClient udpObj←⎕NEW UdpClient udpObj.SendTimeout←_PortTimeOut udpObj.ReceiveTimeout←_PortTimeOut ⍝ Send the data asynchronously to the IPEndPoint task←udpObj.SendAsync(bytes(⍬⍴⍴,bytes)ipep) ⍝ Prepare the task :If 0=⎕TSYNC{task.Wait ⍵}&(_PortTimeOut) ⍝ Failure to send all the data. r←0 'UDP Error Sending: Task did not complete sending the bytes' ⋄ →RETRIES :Else ⍝ Success ⍝ Sending the data seems to work all the time even if the ⍝ ethernet cable is unplug from the computer. task.Dispose :EndIf ⍝ Receive the data asynchronously task←udpObj.ReceiveAsync ⍝ Prepare the task :If ⎕TSYNC{task.Wait ⍵}&(_PortTimeOut) ⍝ Task completed successfully data←task.Result.Buffer task.Dispose r←1 data :Else ⍝ taskResult=0 when no data is received ⍝ Trying to Send again with a udpObj that did ⍝ not received does not work. A new udpObj is required. ⍝ Hence a new UdpClient object for each retry. r←0 'UDP: No Data Received' ⋄ →RETRIES :EndIf RETRIES: retries-←1 ⍝ Clean-up before trying again. :Trap 0 udpObj.Close udpObj←⎕NULL :EndTrap :Until 1=1↑r :Else ⍝ Show the error. :If 90=⎕EN ⍝ .Net Error r←0('UDP Error: ',⎕EXCEPTION.GetBaseException.Message) ⋄ →0 :Else ⍝ APL Error r←0(1⊃⎕DM),': ',{(' '=1↑⍵)↓((1↓a,0)∨a←' '≠⍵)/⍵}(2⊃⎕DM) ⋄ →0 :EndIf :EndTrap ∇ :EndClass