Apple 在 iOS 12 後內建了 Socket 連線,讓我們能夠擺脫以往要使用第三方套件來做 Socket 連線的機制,而 Apple 的 Socket 連線是採用了 NWConnection 這個機制,最近海芋剛好要實做 TCP 連線的機制,在使用 ChatGPT 的幫助下,終於寫好了一個簡單的 Socket 連線程式。

我是以這個關鍵字去問 ChatGPT。
給我一個完整程式,swift 撰寫socket 連線, 在背景執行序執行,
需考慮到連線逾時,傳送過程都是使用byte進行傳送接收 ,
在傳送時需考慮到每一筆資料傳送完成後再送下一筆,使用 NWConnection
結果 ChatGPT 馬上生給我範例程式。
class SocketManager {
private var connection: NWConnection?
private let queue = DispatchQueue(label: "socketQueue")
private let host: NWEndpoint.Host
private let port: NWEndpoint.Port
init(host: String, port: UInt16) {
self.host = NWEndpoint.Host(host)
self.port = NWEndpoint.Port(rawValue: port)!
}
func connect() {
let parameters = NWParameters.tcp
connection = NWConnection(host: host, port: port, using: parameters)
connection?.stateUpdateHandler = { [weak self] newState in
switch newState {
case .ready:
print("Connected!")
self?.receive()
case .failed(let error):
print("Connection failed: \(error)")
self?.connection?.cancel()
case .cancelled:
print("Connection cancelled")
default:
break
}
}
connection?.start(queue: queue)
}
func send(data: Data) {
connection?.send(content: data, completion: .contentProcessed({ [weak self] error in
if let error = error {
print("Send error: \(error)")
} else {
print("Data sent successfully")
}
}))
}
private func receive() {
connection?.receive(minimumIncompleteLength: 1, maximumLength: 65536) { [weak self] (data, context, isComplete, error) in
if let data = data {
print("Received data: \(data)")
}
if isComplete {
self?.connection?.cancel()
} else if let error = error {
print("Receive error: \(error)")
} else {
self?.receive()
}
}
}
func disconnect() {
connection?.cancel()
}
}
不得不說 ChatGPT 真的很厲害,這樣的確就快寫完了。但是在看了 NWParameters 這個物件後,發現有一些優化可以使用。舉例來說,當我們在解析網站時,會從 DNS Server 要到網站的 ip,而 DNS Server 會有快取的機制,但快取的時間是有限制的,舉例來說可能兩小時就過期了,如果我們在連線時能夠將查詢回來的 DNS 結果先儲存,當連不上時再去問 DNS Server,這樣就可以加速連線的時間,這時我們可以將「expiredDNSBehavior」設為 allow,就可以利用這樣的機制了。
private func getParams() -> NWParameters {
// 使用 TCP 連線
let params = NWParameters.tcp
// 允許使用過期的DNS,若連不上iOS會自動重查並重新連上
params.expiredDNSBehavior = .allow
return params
}
另外,如果我們的手機訊號常常在行動網路和wifi間飄移,我們可以採用 Multipath TCP 來做連線,而要開啟這個功能,建議將 multipathServiceType 設為 interactive 或是 aggregate。
private func getParams() -> NWParameters {
// 使用 TCP 連線
let params = NWParameters.tcp
// 降低延遲,並同時使用多種網路連線至站台
params.multipathServiceType = .interactive
return params
}
以上是略舉兩個簡單的應用,相信你已經想試了,有問題就問 ChatGPT 吧,他會給你很好的靈感的。