73 lines
2.2 KiB
Swift
73 lines
2.2 KiB
Swift
// The Swift Programming Language
|
|
// https://docs.swift.org/swift-book
|
|
import NIOCore
|
|
import NIOPosix
|
|
|
|
private final class EchoHandler: ChannelInboundHandler {
|
|
typealias InboundIn = ByteBuffer
|
|
typealias OutboundOut = BackPressureHandler
|
|
|
|
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
|
|
context.write(data, promise: nil)
|
|
}
|
|
|
|
func channelReadComplete(context: ChannelHandlerContext) {
|
|
context.flush()
|
|
}
|
|
|
|
func errorCaught(context: ChannelHandlerContext, error: any Error) {
|
|
print("error: \(error)")
|
|
context.close(promise: nil)
|
|
}
|
|
}
|
|
|
|
let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount)
|
|
let bootstrap = ServerBootstrap(group: group)
|
|
.serverChannelOption(.backlog, value: 256)
|
|
.serverChannelOption(.socketOption(.so_reuseaddr), value: 1)
|
|
// set the handlers that are applied.
|
|
.childChannelInitializer { channel in
|
|
channel.eventLoop.makeCompletedFuture {
|
|
try channel.pipeline.syncOperations.addHandler(BackPressureHandler())
|
|
try channel.pipeline.syncOperations.addHandler(EchoHandler())
|
|
}
|
|
}
|
|
.childChannelOption(.socketOption(.so_reuseaddr), value: 1)
|
|
.childChannelOption(.maxMessagesPerRead, value: 16)
|
|
.childChannelOption(.recvAllocator, value: AdaptiveRecvByteBufferAllocator())
|
|
|
|
defer { try? group.syncShutdownGracefully() }
|
|
|
|
// First argument is the program path
|
|
let arguments = CommandLine.arguments
|
|
let arg1 = arguments.dropFirst().first
|
|
let arg2 = arguments.dropFirst(2).first
|
|
|
|
let defaultHost = "::1"
|
|
let defaultPort = 9999
|
|
|
|
struct BindTo {
|
|
let host: String
|
|
let port: Int
|
|
}
|
|
|
|
let bindTarget: BindTo
|
|
switch (arg1, arg1.flatMap(Int.init), arg2.flatMap(Int.init)) {
|
|
case let (_, .some(port), _):
|
|
bindTarget = .init(host: defaultHost, port: port)
|
|
case let (.some(host), _, .some(port)):
|
|
bindTarget = .init(host: host, port: port)
|
|
case let (.some(host), .none, .none):
|
|
bindTarget = .init(host: host, port: defaultPort)
|
|
default:
|
|
bindTarget = .init(host: defaultHost, port: defaultPort)
|
|
}
|
|
|
|
let channel = try bootstrap.bind(host: bindTarget.host, port: bindTarget.port).wait()
|
|
|
|
print("Server started and listening on: \(channel.localAddress!)")
|
|
|
|
try channel.closeFuture.wait()
|
|
|
|
print("Server closed!")
|