How to send an empty datagram

RFC 868 May 1983 Time Protocol


When used via UDP the time service works as follows:


S: Listen on port 37 (45 octal).


U: Send an empty datagram to port 37.


S: Receive the empty datagram.


S: Send a datagram containing the time as a 32 bit binary number.


U: Receive the time datagram.



While trying to send an empty datagram there is no datagram sent over (checked by wireshark)

even though the send function seems to complete without any error.


How to send an empty datagram with Network.framework?

Please post a snippet of the code you’re using to issue this send.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank for the interest, eskimo!


I've mentioned RFC 868 only as an example of usage, maybe not the best. I would like to send UDP packet with no payload. In reality, such a packet isn't empty, it comes with the sender's identity.


While trying to use nil or empty Data() as a content parameter on 'ready' UDP connection (it has no sense for TCP connection at all)


func send(content: Data?, contentContext: NWConnection.ContentContext = default, isComplete: Bool = default, completion: NWConnection.SendCompletion)


no packet is sent out nor error is reported in the completion handler. Using UDP packet with 0 length payload is useful for signaling.

Using UDP packet with 0 length payload is useful for signaling.

There’s no doubt about that. I’m just curious about the code you’re actually using. Can you post some snippets?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
import Foundation
import Network
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

let connection = NWConnection(host: "::1", port: 6060, using: .udp)
func send(data: Data?, using connection: NWConnection) {
    connection.send(content: data, contentContext: .defaultMessage, isComplete: true, completion: .contentProcessed({ (e) in
        print(e)
    }))
}
connection.stateUpdateHandler = { state in
    print(state)
    if state == .ready {
        send(data: Data(bytes: [255]), using: connection)
    }
}

connection.start(queue: .main)

Running the playgorund I capture the proper frame with wireshark and the snippet prints

preparing
ready
nil

as expected.

While trying to send an empty or nil data (in code line 15 above), independent from contentContext and isComplete parameters in line 08, I don't capture any frame with wireshark and the playground prints the same

preparing
ready
nil



For 'reference' this playground snippet (using socket library) works as expected

import Foundation
import Darwin

let data = Data(bytes: [])
let nsData = data as NSData
let rawPtr = nsData.bytes
let length = nsData.length

var hints = addrinfo()
var paddr: UnsafeMutablePointer?

defer {
    if paddr != nil { freeaddrinfo(paddr) }
}

hints.ai_family = AF_INET6
hints.ai_socktype = SOCK_DGRAM
hints.ai_flags = AI_ADDRCONFIG

// to avoid fill addrinfo manualy :-)
if getaddrinfo("::1", "6060", &hints, &paddr) != 0 {
    print(errno)
    exit(0)
}
if paddr?.pointee.ai_next != nil {
    print("it must be only one addrinfo with ::1 address")
    exit(0)
}
let sock = socket(paddr!.pointee.ai_family, paddr!.pointee.ai_socktype, paddr!.pointee.ai_protocol)
if sock < 0 {
    print(errno)
    exit(0)
}

if sendto(sock, rawPtr, length, 0, paddr!.pointee.ai_addr, paddr!.pointee.ai_addrlen) < 0 {
    print(errno)
    exit(0)
} else {
    print("packet with", nsData, "payload sent successfully")
}

Thanks for the snippets. I pasted them into a test project here in my office and I see the same problem. At this point my recommendation is that you file a bug report, making sure to explain why zero-length UDP datagrams are important.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for Your time and response!

https://bugreport.apple.com/web/?problemID=47594701

Thanks for the bug report (r. 47594701). I just took a look and it’s on its way back to you as a duplicate of an existing bug. This is a known limitation in the current Network framework. We don’t know of any way you can work around it, other than to continue using BSD Sockets )-:

As per the usual Apple policy, I can’t offer any concrete details as to when this will be fixed, but if you ping this thread, oh, I dunno, six months from now, I’ll take another look.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
2 years later still a problem, right?
Our records indicate that this was supposed to be fixed in iOS 13. I haven’t actually tried it myself though. Presumably you tried it and it doesn’t work. Can you post a code snippet demonstrating that?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
How to send an empty datagram
 
 
Q