SwiftNIO:发送和接收 UDP 广播
SwiftNIO: Send and receive UDP broadcast
我正在尝试使用 SwiftNIO 构建 TCP 服务器。服务器在网络中启动,但客户端不知道 ip 地址。因此,我也想启动一个 UDP 服务器,如果客户端出现,他会向网络发送一条广播消息。服务器将接收并应答,以便客户端现在知道 IP 地址。
是否可以使用 SwiftNIO 构建类似的东西?
是的,这是可能的,而且 SwiftNIO 中没有太多支持使这变得容易。
请参阅下面的注释示例,该示例将每秒发送一次 HELLO WORLD
到 en0
的广播地址和端口 37020。
import NIO
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
try! group.syncShutdownGracefully()
}
let matchingInterfaces = try System.enumerateInterfaces().filter {
// find an IPv4 interface named en0 that has a broadcast address.
[=10=].name == "en0" && [=10=].broadcastAddress != nil
}
guard let en0Interface = matchingInterfaces.first, let broadcastAddress = en0Interface.broadcastAddress else {
print("ERROR: No suitable interface found. en0 matches \(matchingInterfaces)")
exit(1)
}
// let's bind the server socket
let server = try! DatagramBootstrap(group: group)
// enable broadast
.channelOption(ChannelOptions.socket(SOL_SOCKET, SO_BROADCAST), value: 1)
.bind(to: en0Interface.address)
.wait()
print("bound to \(server.localAddress!)")
var buffer = server.allocator.buffer(capacity: 32)
buffer.writeString("HELLO WORLD!")
var destAddr = broadcastAddress
destAddr.port = 37020 // we're sending to port 37020
// now let's just send the buffer once a second.
group.next().scheduleRepeatedTask(initialDelay: .seconds(1),
delay: .seconds(1),
notifying: nil) { task in
server.writeAndFlush(AddressedEnvelope(remoteAddress: destAddr,data: buffer)).map {
print("message sent to \(destAddr)")
}.whenFailure { error in
print("ERROR: \(error)")
// and stop if there's an error.
task.cancel()
server.close(promise: nil)
}
}
try server.closeFuture.wait()
如果你想绑定到 0.0.0.0
并发送到 255.255.255.255
你可以使用这个
import NIO
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
try! group.syncShutdownGracefully()
}
// let's bind the server socket
let server = try! DatagramBootstrap(group: group)
// enable broadast
.channelOption(ChannelOptions.socket(SOL_SOCKET, SO_BROADCAST), value: 1)
.bind(to: .init(ipAddress: "0.0.0.0", port: 0))
.wait()
print("bound to \(server.localAddress!)")
var buffer = server.allocator.buffer(capacity: 32)
buffer.writeString("HELLO WORLD!")
// we're sending to port 37020
let destPort = 37020
let destAddress = try SocketAddress(ipAddress: "255.255.255.255", port: destPort)
// now let's just send the buffer once a second.
group.next().scheduleRepeatedTask(initialDelay: .seconds(1),
delay: .seconds(1),
notifying: nil) { task in
server.writeAndFlush(AddressedEnvelope(remoteAddress: destAddress, data: buffer)).map {
print("message sent to \(destAddress)")
}.whenFailure { error in
print("ERROR: \(error)")
// and stop if there's an error.
task.cancel()
server.close(promise: nil)
}
}
try server.closeFuture.wait()
我正在尝试使用 SwiftNIO 构建 TCP 服务器。服务器在网络中启动,但客户端不知道 ip 地址。因此,我也想启动一个 UDP 服务器,如果客户端出现,他会向网络发送一条广播消息。服务器将接收并应答,以便客户端现在知道 IP 地址。
是否可以使用 SwiftNIO 构建类似的东西?
是的,这是可能的,而且 SwiftNIO 中没有太多支持使这变得容易。
请参阅下面的注释示例,该示例将每秒发送一次 HELLO WORLD
到 en0
的广播地址和端口 37020。
import NIO
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
try! group.syncShutdownGracefully()
}
let matchingInterfaces = try System.enumerateInterfaces().filter {
// find an IPv4 interface named en0 that has a broadcast address.
[=10=].name == "en0" && [=10=].broadcastAddress != nil
}
guard let en0Interface = matchingInterfaces.first, let broadcastAddress = en0Interface.broadcastAddress else {
print("ERROR: No suitable interface found. en0 matches \(matchingInterfaces)")
exit(1)
}
// let's bind the server socket
let server = try! DatagramBootstrap(group: group)
// enable broadast
.channelOption(ChannelOptions.socket(SOL_SOCKET, SO_BROADCAST), value: 1)
.bind(to: en0Interface.address)
.wait()
print("bound to \(server.localAddress!)")
var buffer = server.allocator.buffer(capacity: 32)
buffer.writeString("HELLO WORLD!")
var destAddr = broadcastAddress
destAddr.port = 37020 // we're sending to port 37020
// now let's just send the buffer once a second.
group.next().scheduleRepeatedTask(initialDelay: .seconds(1),
delay: .seconds(1),
notifying: nil) { task in
server.writeAndFlush(AddressedEnvelope(remoteAddress: destAddr,data: buffer)).map {
print("message sent to \(destAddr)")
}.whenFailure { error in
print("ERROR: \(error)")
// and stop if there's an error.
task.cancel()
server.close(promise: nil)
}
}
try server.closeFuture.wait()
如果你想绑定到 0.0.0.0
并发送到 255.255.255.255
你可以使用这个
import NIO
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
try! group.syncShutdownGracefully()
}
// let's bind the server socket
let server = try! DatagramBootstrap(group: group)
// enable broadast
.channelOption(ChannelOptions.socket(SOL_SOCKET, SO_BROADCAST), value: 1)
.bind(to: .init(ipAddress: "0.0.0.0", port: 0))
.wait()
print("bound to \(server.localAddress!)")
var buffer = server.allocator.buffer(capacity: 32)
buffer.writeString("HELLO WORLD!")
// we're sending to port 37020
let destPort = 37020
let destAddress = try SocketAddress(ipAddress: "255.255.255.255", port: destPort)
// now let's just send the buffer once a second.
group.next().scheduleRepeatedTask(initialDelay: .seconds(1),
delay: .seconds(1),
notifying: nil) { task in
server.writeAndFlush(AddressedEnvelope(remoteAddress: destAddress, data: buffer)).map {
print("message sent to \(destAddress)")
}.whenFailure { error in
print("ERROR: \(error)")
// and stop if there's an error.
task.cancel()
server.close(promise: nil)
}
}
try server.closeFuture.wait()