writeDataUnsupported в ChannelInboundHandler (Swift-NIO)

Я пытаюсь сделать простой эхо-сервер UDP, который отправляет обратно все входящие дейтаграммы с префиксом строки UTF8.

В моих попытках достичь этой цели мне удалось отправить обратно входящие данные, но когда я пытаюсь поставить перед этими данными префикс строки: "You sent: "Я получаю ошибку writeDataUnsupported

Это мой код:

я сделал ChannelInboundHandler называется Echo все, что он делает: для каждой входящей дейтаграммы он отправляет строку "You sent: " а затем данные входящей дейтаграммы.

final class Echo: ChannelInboundHandler {
    typealias   InboundIn = ByteBuffer
    typealias OutboundOut = ByteBuffer

    var wroteResponse = false
    static let response = "You sent: ".data(using: .utf8)!

    func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
        if !wroteResponse {
            var buffer = ctx.channel.allocator.buffer(capacity: Echo.response.count)
            buffer.write(bytes: Echo.response)
            ctx.write(self.wrapOutboundOut(buffer), promise: nil)
            wroteResponse = true
        }
        ctx.write(data, promise: nil)
    }

    func channelReadComplete(ctx: ChannelHandlerContext) {
        ctx.flush()
        wroteResponse = false
    }
}

Затем я создал однопоточную группу циклов обработки событий и назначил для нее загрузочный цикл дейтаграммы. Затем я привязал загрузчик к порту 4065.

let  = MultiThreadedEventLoopGroup(numThreads: 1)
let bootstrap = DatagramBootstrap(group: )
    .channelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
    .channelInitializer { $0.pipeline.add(handler: Echo()) }
defer {
    try! .syncShutdownGracefully()
}


try bootstrap
    .bind(host: "127.0.0.1", port: 4065)
    .wait()
    .closeFuture
    .wait()

Почему я всегда получаю это writeDataUnsupported при попытке отправить строку: "You sent: "?

2 ответа

Решение

За DatagramChannel вам нужно обернуть ByteBuffer в AddressEnvelope, Что также означает, что ваш ChannelInboundHandler должен работать на AddressedEnvelope<ByteBuffer>,

Чтобы сделать ChannelInboundHandler действуют на AddressedEnvelope<ByteBuffer>Норман Маурер предлагает переписать Echo так что это больше похоже на:

final class Echo: ChannelInboundHandler {
    typealias  InboundIn  = AddressedEnvelope<ByteBuffer>
    typealias OutboundOut = AddressedEnvelope<ByteBuffer>

    static let response = "You sent: ".data(using: .utf8)!

    func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
        var incomingEnvelope = unwrapInboundIn(data)
        var buffer = ctx.channel.allocator.buffer(capacity: Echo.response.count + incomingEnvelope.data.readableBytes)
        buffer.write(bytes: Echo.response)
        buffer.write(buffer: &incomingEnvelope.data)

        let envelope = AddressedEnvelope(remoteAddress: incomingEnvelope.remoteAddress, data: buffer)
        ctx.write(wrapOutboundOut(envelope), promise: nil)
    }

    func channelReadComplete(ctx: ChannelHandlerContext) {
        ctx.flush()
    }
}
Другие вопросы по тегам