UDPSocketRecv
Attempts to receive packets sent to a socket's source port.
Syntax
UDPSocketRecv( BytesReceived, SocketID, InDatagram, InDatagramLen, RemoteIPAdd, RemotePort, Timeout [optional] )
Example #1
' A simple UDP client example sending data to another device and receiving data back
'UDP Variables
Const RecvBufferSize = 200
Public SockID As Long
Public bytesWritten As Long
Public bytesReceived As Long
Public recvDatagramStr As String * RecvBufferSize 'Leave space for null terminator
Public remoteIP As String * 100
Public remotePort As Long
Public recvTimeouts As Long 'increment this if we time out waiting for a response
Public PTemp, Batt_volt
Dim inputSize As Long
Dim recvDatagramBytes(RecvBufferSize) As UINT1 'We are receiving raw bytes back, so use UINT1
DataTable (Test,1,-1)
DataInterval (0,15,Sec,10)
Minimum (1,Batt_volt,FP2,False,False)
Sample (1,PTemp,FP2)
EndTable
'Main Program
BeginProg
Scan (1,Sec,0,0)
Battery (Batt_volt)
CallTable Test
NextScan
SlowSequence
Scan(30,Sec,0,0)
UDPSocketOpen(SockID, 0, 3) 'We are a client, so get an ephemeral port
If (SockID >= 0) Then
'Socket successfully opened
'If you were trying to send to a remote host with a domain name, you would use the DNSQuery instruction here to get the IP associated
' with that domain
'example:
'
' Public ipAddr As String * 100
' DNSQuery(Ret, ipAddr, "domain.com")
' If Ret = 0 Then
' ' We successfully resolved the domain to an IP, put rest of code in here
UDPSocketSend(bytesWritten,SockID,"10.34.10.12", 40000,"Bytes sent over UDP",19) 'size 19 to not include null character
If (bytesWritten >= 0) Then
'Successfully wrote out the message, now get a response
UDPSocketRecv(bytesReceived,SockID,recvDatagramBytes,0,remoteIP,remotePort, 500) 'Wait half a second for a response
If (bytesReceived > 0) Then
'We got a response with a non-zero payload size
If (bytesReceived >= RecvBufferSize) Then
inputSize = RecvBufferSize
'They sent us more bytes than our buffer can hold, so the input was truncated to the size of the buffer.
'Since this is just binary data, we need to add the null terminator ourselves before copying into our string. Since the buffer
'is full, we'll overwrite the last byte of data with a null terminator
recvDatagramBytes(RecvBufferSize) = &h00
Else
inputSize = bytesReceived + 1 'Add 1 for null terminator we are going to add
'We know that we have space in the buffer to add a null terminator without overwriting any data
recvDatagramBytes(inputSize) = &h00
EndIf
'Copy into string variable (this code makes the assumption that all of these bytes are printable characters, which is not an
'assumption actual application should make)
MoveBytes(recvDatagramStr, 0, recvDatagramBytes, 0, inputSize)
ElseIf (bytesReceived = -1) Then
'We timed out waiting for a response
recvTimeouts += 1
EndIf
EndIf
UDPSocketClose(SockID) 'If a socket is successfully opened, it will stay open until it is closed
EndIf
NextScan
EndSequence
EndProg
Example #2
'CR1000X Series Datalogger
'Simple UDP Server application that echos back data that is sent to it
'UDP Variables
Const ServerPort = 40000 'UDP Port the server listens on
Const RecvQueueSize = 10
Const RecvBufferSize = 200
Const PrefixSize = 8
Const SendBufferSize = RecvBufferSize + PrefixSize
Public SockIsOpen As Boolean = FALSE 'Server is listening
Public SockID As Long
Public bytesWritten As Long
Public bytesReceived As Long
Public remoteIP As String * 100
Public remotePort As Long
Public initErrorFlag As Boolean = FALSE 'let user know opening the port failed
Public recvErrorFlag As Boolean = FALSE 'let the user know we had an error while receiving
Public PTemp, Batt_volt
Public recvDatagram(RecvBufferSize) As UINT1
' e c h o - >
Dim sendBuffer(SendBufferSize) As UINT1 = { &h65, &h63, &h68, &h6F, &h20, &h2D, &h3E, &h20 }
Dim inputSize As Long
DataTable (Test,1,-1)
DataInterval (0,15,Sec,10)
Minimum (1,Batt_volt,FP2,False,False)
Sample (1,PTemp,FP2)
EndTable
BeginProg
Scan (1,Sec,0,0)
Battery (Batt_volt)
CallTable Test
NextScan
SlowSequence
Scan (1,Sec,3,0)'Check every second, so messages do not build up
If NOT SockIsOpen Then
UDPSocketOpen(SockID, ServerPort, RecvQueueSize, 1) 'We are a server, so choose a port. Also, set recv queue higher
'so we do not drop messages. Bind to ethernet
If (SockID >= 0) Then
SockIsOpen = TRUE
Else
initErrorFlag = TRUE 'Just let the user know.
EndIf
EndIf
If SockIsOpen Then
'Socket successfully opened
UDPSocketRecv(bytesReceived,SockID,recvDatagram,0,remoteIP,remotePort)
If (bytesReceived >= 0) Then
' We received a datagram. Use the remoteIP and remotePort parameters to send a response back to the device that sent us the datagram
'Copy into send buffer (we are echoing the data back with a prefix of the ASCII bytes 'echo -> ')
If (bytesReceived >= RecvBufferSize) Then
inputSize = RecvBufferSize 'They sent us more bytes than our buffer can hold, so the input was truncated to the size of the buffer.
Else
inputSize = bytesReceived
EndIf
MoveBytes(sendBuffer, PrefixSize, recvDatagram, 0, inputSize)
UDPSocketSend(bytesWritten,SockID,remoteIP,remotePort,sendBuffer,PrefixSize + inputSize) 'A real application should check for an error
ElseIf (bytesReceived < -1) Then
recvErrorFlag = TRUE 'Just let the user know an error happened. A real application should check error codes
EndIf
EndIf
NextScan
EndSequence
EndProg
Example #3
'CR1000X Series Datalogger
'Simple UDP Server application that echos back data that is sent to it
'This example is very similar to Example #2 but uses the blocking functionality of the UDPSocketRecv() Timeout parameter.
'It is not generally recommended to use this functionality, because it could theoretically be waiting for data to come in
'forever. However, if the only thing the program is doing is listening for incoming UDP datagrams and it doesn't matter how often the 'datalogger checks for a new UDP datagram, the blocking functionality is a good option. In this case, the OS is choosing how often to poll for 'incoming data, not the programmer, and it checks many times per second to make sure it provides UDP datagrams processed by the datalogger's 'TCP/IP stack to the program within milliseconds of when they are received.
'UDP Variables
Const ServerPort = 40000 'UDP Port the server listens on
Const RecvQueueSize = 10
Const RecvBufferSize = 200
Const PrefixSize = 8
Const SendBufferSize = RecvBufferSize + PrefixSize
Public SockIsOpen As Boolean = FALSE 'Server is listening
Public SockID As Long
Public bytesWritten As Long
Public bytesReceived As Long
Public remoteIP As String * 100
Public remotePort As Long
Public initErrorFlag As Boolean = FALSE 'let user know opening the port failed
Public recvErrorFlag As Boolean = FALSE 'let the user know we had an error while receiving
Public PTemp, Batt_volt
Public recvDatagram(RecvBufferSize) As UINT1
' e c h o - >
Dim sendBuffer(SendBufferSize) As UINT1 = { &h65, &h63, &h68, &h6F, &h20, &h2D, &h3E, &h20 }
Dim inputSize As Long
DataTable (Test,1,-1)
DataInterval (0,15,Sec,10)
Minimum (1,Batt_volt,FP2,False,False)
Sample (1,PTemp,FP2)
EndTable
BeginProg
Scan (1,Sec,0,0)
Battery (Batt_volt)
CallTable Test
NextScan
SlowSequence
While 1
If NOT SockIsOpen Then
UDPSocketOpen(SockID, ServerPort, RecvQueueSize, 1) 'We are a server, so choose a port. Also, set recv queue higher
'so we do not drop messages. Bind to ethernet
If (SockID >= 0) Then
SockIsOpen = TRUE
Else
initErrorFlag = TRUE 'Just let the user know.
EndIf
EndIf
If SockIsOpen Then
'Socket successfully opened
UDPSocketRecv(bytesReceived,SockID,recvDatagram,0,remoteIP,remotePort,-1)
If (bytesReceived >= 0) Then
' We received a datagram. Use the remoteIP and remotePort parameters to send a response back to the device that sent us the datagram
'Copy into send buffer (we are echoing the data back with a prefix of the ASCII bytes 'echo -> ')
If (bytesReceived >= RecvBufferSize) Then
inputSize = RecvBufferSize 'They sent us more bytes than our buffer can hold, so the input was truncated to the size of the buffer.
Else
inputSize = bytesReceived
EndIf
MoveBytes(sendBuffer, PrefixSize, recvDatagram, 0, inputSize)
UDPSocketSend(bytesWritten,SockID,remoteIP,remotePort,sendBuffer,PrefixSize + inputSize) 'A real application should check for an error
ElseIf (bytesReceived < -1) Then
recvErrorFlag = TRUE 'Just let the user know an error happened. A real application should check error codes
EndIf
EndIf
Wend
EndSequence
EndProg
Remarks
UDPSocketRecv() attempts to receive packets sent to a sockets source port.
Parameters
BytesReceived
Number of bytes received (>= 0 since it is possible to receive a 0 length datagram). If -1, no data has been received (if a timeout was specified this means we timed out). If < -1, an error occurred. The values that can be returned are:
| Code | Description |
|---|---|
| >=0 | Received a datagram with a payload of this many bytes. (It is possible to receive a zero-length UDP datagram.) |
| -1 | Did not receive a datagram, even after potentially waiting if a timeout was set. |
| -2 | Socket not initialized or was closed. (The only way this will be closed is if you call UDPSocketClose.) |
| -4 | Invalid InDatagramLen (negative or greater than the size of the buffer) |
|
-6 |
Invalid SocketID. |
Type: Variable of type Long
SocketID
Socket ID returned from a call to UDPSocketOpen().
Type: Constant or Variable of type Long
InDatagram
Variable in which to store the datagram payload.
InDatagramLen
The size of InDatagram (or how many bytes you wish to be stored). If this parameter is 0, all of the variable's memory will be used.
Type: Variable of Type Long
RemoteIPAddr
IP address of the remote device that sent this datagram (can be passed to UDPSocketSend() to send a datagram to this device).
Type: Constant or Variable of Type String
RemotePort
Port of the remote device that sent this datagram (can be passed to UDPSocketSend() to send a datagram to this device).
Type: Constant or Variable of Type Long
Optional Parameters
Timeout
Timeout in milliseconds to wait for an incoming datagram (if one has not already been received). If 0 (or not specified), we will not wait at all. If there are no datagrams that have been received at the time of calling this instruction or we time out while waiting for incoming packets, -1 is written to the BytesReceived parameter. If this parameter is less than 0, this call will block execution (in its sequence) until a packet comes in or an error occurs. Do not use this functionality when in a scan, since theoretically this could block execution forever (if no packets come in) and cause skipped scans. It is recommended to put this instruction in a scan and periodically check it instead of using this blocking functionality, as datalogger operation is optimized internally by using scans (using the block execution functionality can be less efficient since the datalogger is constantly polling for input).
Type: Constant or Variable of Type Long