Accepted Reply
I want to see Apple’s TCP sample code …
Apple platforms support many different TCP APIs. The TCPTransports sample code shows four of thsee APIs (
CFSocketStream
,
NSURLSessionStreamTask
, BSD Sockets, and
NWTCPConnection
).
The only remaining API is the Network framework, for which there isn’t a good official sample yet [1]. We are working on addressing that, but for the moment, I’ve pasted a tiny example in below, just to get your started.
If you have any further questions about any of these APIs, I’m happy to answer them.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
[1] There’s nwcat, but it has a number of drawbacks, not least of which is that it’s a C sample.
import Foundation
import Network
class Main {
init(hostName: String, port: Int) {
let host = NWEndpoint.Host(hostName)
let port = NWEndpoint.Port("\(port)")!
self.connection = NWConnection(host: host, port: port, using: .tcp)
}
let connection: NWConnection
func start() {
NSLog("will start")
self.connection.stateUpdateHandler = self.didChange(state:)
self.startReceive()
self.connection.start(queue: .main)
}
func stop() {
self.connection.cancel()
NSLog("did stop")
}
private func didChange(state: NWConnection.State) {
switch state {
case .setup:
break
case .waiting(let error):
NSLog("is waiting: %@", "\(error)")
case .preparing:
break
case .ready:
break
case .failed(let error):
NSLog("did fail, error: %@", "\(error)")
self.stop()
case .cancelled:
NSLog("was cancelled")
self.stop()
@unknown default:
break
}
}
private func startReceive() {
self.connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, _, isDone, error in
if let data = data, !data.isEmpty {
NSLog("did receive, data: %@", data as NSData)
}
if let error = error {
NSLog("did receive, error: %@", "\(error)")
self.stop()
return
}
if isDone {
NSLog("did receive, EOF")
self.stop()
return
}
self.startReceive()
}
}
func send(line: String) {
let data = Data("\(line)\r\n".utf8)
self.connection.send(content: data, completion: NWConnection.SendCompletion.contentProcessed { error in
if let error = error {
NSLog("did send, error: %@", "\(error)")
self.stop()
} else {
NSLog("did send, data: %@", data as NSData)
}
})
}
static func run() -> Never {
let m = Main(hostName: "127.0.0.1", port: 12345)
m.start()
let t = DispatchSource.makeTimerSource(queue: .main)
var counter = 99
t.setEventHandler {
m.send(line: "\(counter) bottles of beer on the wall.")
counter -= 1
if counter == 0 {
m.stop()
exit(EXIT_SUCCESS)
}
}
t.schedule(wallDeadline: .now() + 1.0, repeating: 1.0)
t.activate()
dispatchMain()
}
}
Main.run()
Replies
I want to see Apple’s TCP sample code …
Apple platforms support many different TCP APIs. The TCPTransports sample code shows four of thsee APIs (
CFSocketStream
,
NSURLSessionStreamTask
, BSD Sockets, and
NWTCPConnection
).
The only remaining API is the Network framework, for which there isn’t a good official sample yet [1]. We are working on addressing that, but for the moment, I’ve pasted a tiny example in below, just to get your started.
If you have any further questions about any of these APIs, I’m happy to answer them.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
[1] There’s nwcat, but it has a number of drawbacks, not least of which is that it’s a C sample.
import Foundation
import Network
class Main {
init(hostName: String, port: Int) {
let host = NWEndpoint.Host(hostName)
let port = NWEndpoint.Port("\(port)")!
self.connection = NWConnection(host: host, port: port, using: .tcp)
}
let connection: NWConnection
func start() {
NSLog("will start")
self.connection.stateUpdateHandler = self.didChange(state:)
self.startReceive()
self.connection.start(queue: .main)
}
func stop() {
self.connection.cancel()
NSLog("did stop")
}
private func didChange(state: NWConnection.State) {
switch state {
case .setup:
break
case .waiting(let error):
NSLog("is waiting: %@", "\(error)")
case .preparing:
break
case .ready:
break
case .failed(let error):
NSLog("did fail, error: %@", "\(error)")
self.stop()
case .cancelled:
NSLog("was cancelled")
self.stop()
@unknown default:
break
}
}
private func startReceive() {
self.connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, _, isDone, error in
if let data = data, !data.isEmpty {
NSLog("did receive, data: %@", data as NSData)
}
if let error = error {
NSLog("did receive, error: %@", "\(error)")
self.stop()
return
}
if isDone {
NSLog("did receive, EOF")
self.stop()
return
}
self.startReceive()
}
}
func send(line: String) {
let data = Data("\(line)\r\n".utf8)
self.connection.send(content: data, completion: NWConnection.SendCompletion.contentProcessed { error in
if let error = error {
NSLog("did send, error: %@", "\(error)")
self.stop()
} else {
NSLog("did send, data: %@", data as NSData)
}
})
}
static func run() -> Never {
let m = Main(hostName: "127.0.0.1", port: 12345)
m.start()
let t = DispatchSource.makeTimerSource(queue: .main)
var counter = 99
t.setEventHandler {
m.send(line: "\(counter) bottles of beer on the wall.")
counter -= 1
if counter == 0 {
m.stop()
exit(EXIT_SUCCESS)
}
}
t.schedule(wallDeadline: .now() + 1.0, repeating: 1.0)
t.activate()
dispatchMain()
}
}
Main.run()
Thank you!
This is Swift sample code. I haven't started to learn Swift. Have Objective-C edition ?
Have Objective-C edition ?
Network framework has no Objective-C API. Your choices are:
Swift, as shown by my snippet above
Plain ol’ C, as shown by nwcat
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
Ok, thanks.
However, I cannot figure out how to set ye DispatchQueues or tasks when staring it from SwiftUI (initially on macOS) . Any ideas, the error message is below:
==
2021-01-08 17:14:48.505411+0200 Display0183 M.[33431:2246222] [general] Attempting to perform block on main runloop, but the main thread has exited. This message will only log once. Break on CFRunLoopErrorMainThreadHasExited to debug.
2021-01-08 17:14:48.505517+0200 Display0183 M.[33431:2246222] [general] Attempting to wake up main runloop, but the main thread as exited. This message will only log once. Break on CFRunLoopErrorMainThreadHasExited to debug.
Assertion failed: (NSViewIsCurrentlyBuildingLayerTreeForDisplay() != currentlyBuildingLayerTree), function NSViewSetCurrentlyBuildingLayerTreeForDisplay, file /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-2022.20.119/AppKit.subproj/NSView.m, line 13401.
Tag it with Network so that I see it.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
Hi Folks,
Whenever I try to make the connection I got the following message :
[connection] nw_socket_handle_socket_event [C1:1] Socket SO_ERROR [61: Connection refused] 2022-09-20 12:26:27.695439+0530 NetworkSample[6165:1970925] [connection] nw_read_request_report [C1] Receive failed with error "Connection refused" 2022-09-20 12:26:27.711315+0530 NetworkSample[6165:1970930] did receive, error: POSIXErrorCode(rawValue: 61): Connection refused 2022-09-20 12:26:27.711474+0530 NetworkSample[6165:1970930] did stop 2022-09-20 12:26:32.685079+0530 NetworkSample[6165:1970930] is waiting: POSIXErrorCode(rawValue: 61): Connection refused 2022-09-20 12:26:37.971629+0530 NetworkSample[6165:1970930] was cancelled 2022-09-20 12:26:39.410259+0530 NetworkSample[6165:1970930] did stop 2022-09-20 12:26:39.410312+0530 NetworkSample[6165:1970926] [connection] [C1 192.168.1.17:8080 tcp, attribution: developer] is already cancelled, ignoring cancel
I am using that code snippets
class Main {
init(hostName: String, port: Int) {
let host = NWEndpoint.Host(hostName)
let port = NWEndpoint.Port("\(port)")!
self.connection = NWConnection(host: host, port: port, using: .tcp)
}
let connection: NWConnection
func start() {
NSLog("will start")
self.connection.stateUpdateHandler = self.didChange(state:)
self.startReceive()
self.connection.start(queue: .main)
}
func stop() {
self.connection.cancel()
NSLog("did stop")
}
private func didChange(state: NWConnection.State) {
switch state {
case .setup:
break
case .waiting(let error):
NSLog("is waiting: %@", "\(error)")
case .preparing:
break
case .ready:
break
case .failed(let error):
NSLog("did fail, error: %@", "\(error)")
self.stop()
case .cancelled:
NSLog("was cancelled")
self.stop()
@unknown default:
break
}
}
private func startReceive() {
self.connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, _, isDone, error in
if let data = data, !data.isEmpty {
NSLog("did receive, data: %@", data as NSData)
}
if let error = error {
NSLog("did receive, error: %@", "\(error)")
self.stop()
return
}
if isDone {
NSLog("did receive, EOF")
self.stop()
return
}
self.startReceive()
}
}
func send(line: String) {
let data = Data("\(line)\r\n".utf8)
self.connection.send(content: data, completion: NWConnection.SendCompletion.contentProcessed { error in
if let error = error {
NSLog("did send, error: %@", "\(error)")
self.stop()
} else {
NSLog("did send, data: %@", data as NSData)
}
})
}
static func run() -> Never {
let m = Main(hostName: "192.168.1.17", port: 8080)
m.start()
let t = DispatchSource.makeTimerSource(queue: .main)
var counter = 99
t.setEventHandler {
m.send(line: "\(counter) bottles of beer on the wall.")
counter -= 1
if counter == 0 {
m.stop()
exit(EXIT_SUCCESS)
}
}
t.schedule(wallDeadline: .now() + 1.0, repeating: 1.0)
t.activate()
dispatchMain()
}
}
I recommend that you start a new thread for this. I’m going to lock this thread because I don’t want it to become the one super mega thread that covers all networking issues.
Tag your new thread with Network so that I see it. Also, feel free to reference back to this thread if there’s something relevant that you want to call out.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"