ios - Swift UDP 连接问题
问题描述
protocol UDPListener {
func handleResponse(_ client: UDPConnection, data: Data)
}
class UDPConnection{
var connection: NWConnection?
var listner: NWListener?
var delegate: UDPListener?
let parameters = NWParameters.udp
// for connect with device
func connect(withHost: NWEndpoint.Host, port: NWEndpoint.Port) {
parameters.allowLocalEndpointReuse = true
self.connection = NWConnection(host: withHost, port: port, using: parameters)
self.connection?.stateUpdateHandler = { (newState) in
switch (newState) {
case .ready:
print("connection ready")
case .setup:
print("connectionsetup")
case .cancelled:
print("connectioncancelled")
case .preparing:
print("connection Preparing")
default:
print("connection waiting or failed")
}
}
self.connection?.start(queue: .global())
}
// for sending UDP string
func sendUDP(_ content: String) {
let contentToSendUDP = content.data(using: String.Encoding.utf8)
self.connection?.send(content: contentToSendUDP, completion: NWConnection.SendCompletion.contentProcessed(({ (NWError) in
if (NWError == nil) {
print("Data was sent to UDP")
} else {
print("ERROR SEND! Error when data (Type: Data) sending. NWError: \n \(NWError!)")
}
})))
}
//for sending UDP data
func sendUDP(_ content: Data) {
self.connection?.send(content: content, completion: NWConnection.SendCompletion.contentProcessed(({ (NWError) in
if (NWError == nil) {
print("Data was sent to UDP")
} else {
print("ERROR Send! Error when data (Type: Data) sending. NWError: \n \(NWError!)")
}
})))
}
//////////////// UDP LISTNER /////////////////////
func listenUDP(port: NWEndpoint.Port) {
do {
parameters.allowLocalEndpointReuse = true
self.listner = try NWListener(using: parameters, on: port)
self.listner?.stateUpdateHandler = {(newState) in
switch newState {
case .ready:
print("Listner ready")
case .failed:
print("Listner failed")
case .cancelled:
print("Listner cancelled")
default:
break
}
}
self.listner?.newConnectionHandler = {(newConnection) in
newConnection.stateUpdateHandler = {newState in
switch newState {
case .ready:
print("new connection establish")
self.receive(on: newConnection)
case .failed:
print("new connection failed")
case .cancelled:
print("new connection cancelled")
default:
break
}
}
newConnection.start(queue: DispatchQueue(label: "new client"))
}
} catch {
print("unable to create listener")
}
self.listner?.start(queue: .global())
}
func receive(on connection: NWConnection) {
connection.receiveMessage { (data, context, isComplete, error) in
if !isComplete {
print("Not Complete")
}
if let error = error {
print("Error in REceive: - ",error)
return
}
if let data = data, !data.isEmpty {
// let backToString = String(decoding: data, as: UTF8.self)
// print("Received Data: ",backToString)
guard self.delegate != nil else {
print("Error Receive: UDPClient response handler is nil")
return
}
print("Data receive in UDPConenction;")
self.delegate?.handleResponse(self, data: data)
}
}
}
}
在这里,我附上了我的 UDP 文件,其中包含 UDP 的连接和侦听器。
当我第一次发送一些数据时,它会发送数据并接收数据。
但是当我再次发送数据时,数据将被发送,但我第二次及以后都没有收到数据。Listner 不再列出。将发送数据,但侦听器未在侦听。
如果我关闭应用程序并再次运行它,则会出现同样的问题。第一次加载数据(监听器监听数据),但第二次监听器不工作。
我的代码有什么问题?我尝试了很多但没有解决问题。请任何可以解决我的问题的人都会非常感谢我。
先感谢您。
解决方案
如果您在此处查看文档,则在您的功能receive
中使用:NWConnection.receiveMessage
https://developer.apple.com/documentation/network/nwconnection/3020638-receivemessage
您会看到它安排了一个接收完成处理程序。这意味着您必须做一些事情才能再次触发它。我通常做的是具有如下功能:
private func setupReceive() {
connection.receive(minimumIncompleteLength: 1, maximumLength: MTU) { (data, _, isComplete, error) in
if let data = data, !data.isEmpty {
let message = String(data: data, encoding: .utf8)
print("connection \(self.id) did receive, data: \(data as NSData) string: \(message ?? "-")")
self.send(data: data)
}
if isComplete {
self.connectionDidEnd()
} else if let error = error {
self.connectionDidFail(error: error)
} else {
self.setupReceive() // HERE I SET THE RECEIVE AGAIN
}
}
}
这样,在处理读取之后,您最终会设置另一个接收完成处理程序。
如果你想看一个完整的例子,你可以在Network.framework
这里查看我关于使用的文章:
https://rderik.com/blog/building-a-server-client-aplication-using-apple-s-network-framework/
该示例使用 TCP 而不是 UDP,但它应该给出一个大致的概念。
推荐阅读
- javascript - 移动网站可以进行生物认证吗?
- html - 叠加背景不会填满所有容器高度
- regex - 如何使用 2 个参数更改 URL 格式以清除子目录中的 URL?
- c# - Azure 错误:“DB2OLEDB”提供程序未在本地计算机上注册
- ruby - 由于 NoSuchElementError,Ruby 移动应用程序测试失败
- python - Tkinter 无效的命令名称“.!button”
- node.js - 使用 httpclients axios 和 request-promise 在 node/express js 中读取响应 HEADER 时,大写转换为小写
- jenkins - 将指标动态添加到 Fabric8 MetricSpecBuilder
- amazon-web-services - 将 Elastic Beanstalk 日志迁移到 S3
- amazon-web-services - 如何创建亚马逊 ssm 自动化文档,用于从多个帐户集中修补