我正在尝试使用 SwiftNIO 构建 TCP 服务器。服务器在网络中启动,但客户端不知道 IP 地址。因此,我也想启动一个 UDP 服务器,如果客户端出现,他会向网络发送广播消息。服务器将接收并回答,以便客户端现在知道 IP 地址。
是否可以使用 SwiftNIO 构建类似的东西?
我正在尝试使用 SwiftNIO 构建 TCP 服务器。服务器在网络中启动,但客户端不知道 IP 地址。因此,我也想启动一个 UDP 服务器,如果客户端出现,他会向网络发送广播消息。服务器将接收并回答,以便客户端现在知道 IP 地址。
是否可以使用 SwiftNIO 构建类似的东西?
是的,这也是可能的,SwiftNIO 中也没有太多支持来简化这件事。请参阅下面的注释示例,该示例将每秒向的广播地址和端口 37020发送HELLO WORLD
一次。en0
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.
$0.name == "en0" && $0.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()