iOS sockets

Hallo,


I have one or two questions to sockets on iOS.

I have to work with UDP and TCP sockets on iOS.


What API oder Framework would you suggest me to solve this problem?

Working with low-level BSD sockets? Use a high-level framework? Which one (there are a lot)?

Use special OS classes with more support? I don't know what is the best thing for my issue.


My requirements for the socket issue:

- TCP and UDP needed

- NO_DELAY support needed

- TCP socket with long-term-connection (not only a few seconds)

- To use the sockets in Swift (if possible)


One more hit from me:

Currently, I worked with NWConnection and DispatchQueue API.

I liked this classes until now. But I find no solution for NO_DELAY issue here (which worked).


        let tcp = NWProtocolTCP.Options.init()
        tcp.noDelay = true
        let params = NWParameters.init(tls: nil, tcp: tcp)
        
        connection = NWConnection(to: NWEndpoint.hostPort(host: ipAddress, port: TcpSocket.PORT), using: params)
       


That was my test to set the NO_DELAY flag for the TCP socket. Is that right?


Would be fine and great to here from you.

Thanks a lot!

Answered by DTS Engineer in 374139022

What exactly you mean with Network framework?

I think I found the first answer in the web

Correct.

Unfortunately I don't see any difference with and without the flag. I see the data in my log a few seconds later …

The Nagle algorithm won’t delay your data for a few seconds (unless your network latency is ginormous). Something else is causing this delay.

Looking at your code, I believe the delay is being triggered by your use of

receiveMessage(…)
. TCP is not a message-oriented protocol, and thus
receiveMessage(…)
doesn’t make any sense [1]. What you want is
receive(minimumIncompleteLength:maximumLength:completion:)
.

Note In iOS 13 beta and friends you can push a framer on to your

NWConnection
. The framer takes care of framing messages to the TCP connection and unframing messages from that connection, allowing you to work in terms of sending and receiving messages. This is super neat but, alas, not available on currently shipping systems.

For more details on this upcoming feature, see WWDC 2019 Session 713 Advances in Networking, Part 2.

Share and Enjoy

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

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

[1] I believe it’s delaying the delivery of data until the TCP connection closes, but I’ve not looked into that case in detail.

I have to work with UDP and TCP sockets on iOS. What API [or] framework would you suggest me to solve this problem?

In general, I’d recommend Network framework, especially if you’re working from Swift. There are two reasons for using older APIs:

  • If you need to support systems prior to iOS 12 (A).

  • If the Network framework is missing features you need (B).

You’ll have to make up your own mind about A. With regards B, Network framework has pretty good feature coverage. The only big item that it’s missing is support for UDP broadcast and multicast. If those are critical to you, you’ll need to use BSD Sockets.

With regards

NO_DELAY
, the snippet you posted, which sets the
noDelay
on
NWProtocolTCP
, is the correct way to handle that.

Share and Enjoy

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

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

Thanks a lot for your reply.


>> In general, I’d recommend Network framework, especially if you’re working from Swift

What exactly you mean with Network framework? An external lib or Core OS SDK? I would like to use high level SDK classes, if it's possible. Something like NWConnection or there are better alternatives? And I would love to use Swift.


>> There are two reasons for using older APIs:

The mentioned two reasons from you (A) and (B) are not relevant for me, now.

Only thing (B) could be relevant in the future, but not really now (so I'd put it in the back).


>> With regards

NO_DELAY
, the snippet you posted, which sets the
noDelay
on
NWProtocolTCP
, is the correct way to handle that.

Okay, thanks. Unfortunately I don't see any difference with and without the flag.

I see the data in my log a few seconds later (after Wireshark). Any ideas? I could also post my code here.

class TcpSocket {
    
    static let PORT: NWEndpoint.Port = 33120
    var connection: NWConnection!
    
    func connectToTcp(ipAddress: NWEndpoint.Host) {
        let queue = DispatchQueue(label: "TCP Client Queue")
        
        let tcp = NWProtocolTCP.Options.init()
        tcp.noDelay = true
        let params = NWParameters.init(tls: nil, tcp: tcp)
        connection = NWConnection(to: NWEndpoint.hostPort(host: ipAddress, port: TcpSocket.PORT), using: params)
        
        connection.stateUpdateHandler = { (newState) in

            switch (newState) {
            case .ready:
                print("Socket State: Ready")
                self.send()
                self.receive()
            default:
            }
        }
        connection.start(queue: queue)
    }
    
    func receive() {
        connection.receiveMessage { (data, context, isComplete, error) in
            if (isComplete) {
  print("Receive is complete, count bytes: \(data!.count)")
                if (data != nil) {
                    print(data!.byteToHex())
                } else {
                    print("Data == nil")
                }
            }
        }
    }
    
    func send() {
        let content: Data = „DummyData“.hexToData()
        connection.send(content: content, completion: NWConnection.SendCompletion.contentProcessed(({ (NWError) in
            if (NWError == nil) {
                print("Data was sent to TCP destination ")
            } else {
                print("ERROR! Error when data (Type: Data) sending. NWError: \n \(NWError!)")
            }
        })))
    }
}


Here is my code: my problem is the receive code in line 29, here is my socket stopped and wait round about 8 seconds for the "socket received READ_CLOSE event". that takes pretty much 8-9 seconds every time. Can this timer be changed? Or maybe deactivated? I want the messages from the IP stack instantly not delayed.

>> What exactly you mean with Network framework? An external lib or Core OS SDK?

I think I found the first answer in the web [1]. IMHO you mean with Network framework classes from die SDK.

E.g. NWConnection, NWEndpoint, NWParameters etc. (see prefix NW for Network Framework ^^)


[1] https://developer.apple.com/documentation/network

Accepted Answer

What exactly you mean with Network framework?

I think I found the first answer in the web

Correct.

Unfortunately I don't see any difference with and without the flag. I see the data in my log a few seconds later …

The Nagle algorithm won’t delay your data for a few seconds (unless your network latency is ginormous). Something else is causing this delay.

Looking at your code, I believe the delay is being triggered by your use of

receiveMessage(…)
. TCP is not a message-oriented protocol, and thus
receiveMessage(…)
doesn’t make any sense [1]. What you want is
receive(minimumIncompleteLength:maximumLength:completion:)
.

Note In iOS 13 beta and friends you can push a framer on to your

NWConnection
. The framer takes care of framing messages to the TCP connection and unframing messages from that connection, allowing you to work in terms of sending and receiving messages. This is super neat but, alas, not available on currently shipping systems.

For more details on this upcoming feature, see WWDC 2019 Session 713 Advances in Networking, Part 2.

Share and Enjoy

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

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

[1] I believe it’s delaying the delivery of data until the TCP connection closes, but I’ve not looked into that case in detail.

>> Looking at your code, I believe the delay is being triggered by your use of

receiveMessage(…)
.

>> TCP is not a message-oriented protocol, and thus

receiveMessage(…)
doesn’t make any sense [1].

What are the use-cases for "receiveMessage()" function?


>> What you want is

receive(minimumIncompleteLength:maximumLength:completion:)
.

Oh yes, absolutely right! Thanks a lot!


>> Note In iOS 13 beta and friends you can push a framer on to your

NWConnection
.

>> The framer takes care of framing messages to the TCP connection and unframing messages from that connection,

>> allowing you to work in terms of sending and receiving messages.

This is really amazing and great! Really cool.

What are the use-cases for receiveMessage() function?

Currently this only make sense for datagram protocols. Right now the only datagram protocol supported is UDP, although in iOS 13 beta we also have raw IP.

It’s also intended to be used for message-oriented protocols. In iOS 13 beta we’ve added support for WebSocket. We’ve also added support for custom framers, so you can build your own message-oriented protocol on top of TCP. You could also imagine this being used for something like QUIC, which is a message-oriented protocol built on top of UDP.

Share and Enjoy

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

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

Thanks a lot for your help!

iOS sockets
 
 
Q