Skip to main content

%Net.UDP

class %Net.UDP extends %Library.RegisteredObject


UDP Communications

A typical model is that you have a provider that waits to receive msgs from many hosts on a well defined port, and there are many requestors that send pkts to the provider.

Basically a provider creates a UDP object and waits for a request and then responds to the request (if it is required).

  	s prv=##class(%Net.UDP).%New([port num])	// new a provider that can receive
  							// pkts on a well defined port
  	s pkt=prv.Recv([time out])			// Waits for a pkt to arrive or times out
  	s bytes=prv.Reply([answer pkt])			// send a pkt back to the requestor.
  

The requestor must know the host and port or the subnet and port to send or broadcast a packet to.

  	s clnt=##class(%Net.UDP).%New()				// Create an anonymous requestor
  	  							// using a dynamic port num
  	s bytes=clnt.Send([pkt],[host or subnet],[port])	// send a pkt to the provider
  
i.e.
  	 
  	;;       Provider			;		Requestor
  	   s prv=##class(%Net.UDP).%New(2050)	;
  						s clnt=##class(%Net.UDP).%New()
  						s host=##class(%Net.UDP).GetHostAddr("localhost")
  						w clnt.Send("Hello 2050",host,2050)
  						; 10
  	   w "Provider Rcvd=",prv.Recv()		
  	;Provider Rcvd=Hello 2050			
  	   w prv.Reply("A msg from 2050")		
  	;15   		      	   
  						w "Requestor rcvd=",clnt.Recv()
  						; Requestor rcvd=A msg from 2050
  	  w "pkt was from=",$system.INetInfo.AddrToHostName(prv.LastAddr),":",prv.LastPort,!
  	;pkt was from=localhost:58135
  

On some platforms the sender and receiver must have the same IP protocol for the packets to reach each other or the UDP object must be bound to the same type of IP protocol as the destination so it can send, otherwise send will fail and it will return -1. i.e. the sender or receiver UDP socket must be bound to IPv4 or IPv6 explicitly . You can specify the IPv4 or IPv6 protocol type when you %New the UDP object. You do this by specifying the default host IP format. Based on this host IP format, UDP binds and communicates using that protocol type:

  s u=##class(%Net.UDP).%New(3001,"::")			// IPv6
  s u=##class(%Net.UDP).%New(3002,"0.0.0.0")		// IPv4
  
You can use netstat -an to find out how it's bound!!

UDP 0.0.0.0:3002 *:*

UDP [::]:3001 *:*

If the UDP object is only a sender with a default port you can pass zero for port num.
  s u=##class(%Net.UDP).%New(0,"::")			// IPv6
  s u=##class(%Net.UDP).%New(0,"0.0.0.0")		// IPv4
  

Note: On some platforms it may require two different UDP objects one for IPv4 and one for IPv6 communication.

In the following example the sender is bound to IPv4 and it cannot send to a IPv6 destination.

  s h=##class(%Net.UDP).GetHostAddr("::1")
  s c=##class(%Net.UDP).%New() 
  w c.Send("chello",h,3002)
  -1
  
  s c=##class(%Net.UDP).%New(0,"::") 
  w c.Send("hello",h,3002)
  5
  

Note that UDP is an unreliable protocol; it may drop some pkts.

It's recommended to send or reply to packets in some canonical format, especially on a Unicode system (i.e. lists, or UTF8).

Property Inventory

Method Inventory

Properties

property LastAddr as %String;
Property methods: LastAddrDisplayToLogical(), LastAddrIsValid(), LastAddrLogicalToDisplay(), LastAddrLogicalToOdbc(), LastAddrNormalize(), LastAddrSet()
property LastPort as %Integer;
Property methods: LastPortDisplayToLogical(), LastPortIsValid(), LastPortLogicalToDisplay(), LastPortNormalize(), LastPortSet()

Methods

method %OnNew(port As %Integer = 0, host As %String = "", timeout As %Integer = 0, sendsiz As %Integer = 0, rcvsiz As %Integer = 0) as %Library.Status

This callback method is invoked by the %New method to provide notification that a new instance of an object is being created.

If this method returns an error then the object will not be created.

%New instantiates a new UDP datagram socket. If host and a port is specified, the socket will be bound to that host and IP. If the specified host and port is in use, it will retry once every second for the specified timeout duration until it becomes available. If a timeout is not specified it will try to bind to that host and port only once.

On success it will return a %Net.UDP object/oref, on failure it will return "".

If rcvsiz or sendsiz are provided the socket is initialized to send and receive at least that size packet.

The default receive buffer size is 16k (16384 bytes).

classmethod GetHostAddr(host As %String) as %String
Converts the passed in host name or IP to a binary form of the IP for efficient use by the Send() method. The returned IP is IPv4 or IPv6 depending on the instance setting.

The returned IP could be converted to a text format by.

  w $system.INetInfo.AddrToHostName(x)
  
method Recv(timeout As %Integer = 0) as %String
Receives a packet from the socket.

It takes an optional timeout. It returns an empty string after the specified seconds.

The returned string is the received raw pkt data. It might be truncated to the specified receive buffer length (Receive length is specified during the class instantiation).

The sender's host and port can be accessed through LastAddr and LastPort properties.

method Reply(pkt As %String) as %Integer
It's exactly the same as the Send() method, except it doesn't require the destination address. It sends to the last received Recv source.
method Send(pkt As %String, dest As %String, port As %Integer) as %Integer
Send a packet to a specified destination and port.

Destination is in $system.INetInfo.INetBinaryAddrToText() or %Net.UDP.GetHostAddr() format (basically an IPv4 or IPv6 binary address).

The port must be a 16 bit port number.

The Send method returns the number of bytes sent.

Inherited Members

Inherited Methods

FeedbackOpens in a new tab