I'm newbie with swift and swift nio too. I want to use ios device like udp socket server for capture image from video and send this image to client connect to server. I use netcat on mac os for testing my code. With short text, netcat client received successfully. But with image data, nothing to response. Where is my faults?
import Foundation
import NIOCore
import NIOPosix
private final class ClientHandler: ChannelInboundHandler {
typealias InboundIn = AddressedEnvelope<ByteBuffer>
typealias OutboundOut = AddressedEnvelope<ByteBuffer>
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
let incomingEnvelope = unwrapInboundIn(data)
let videoCapture = VideoCapture.shared()
if videoCapture.videoUrl == nil {
if let url = Bundle.main.url(
forResource: "video",
withExtension: "mp4"
) {
videoCapture.setGenerator(url: url)
}
}
guard let imgData = videoCapture.readFrame() else { return }
let encodedData = imgData.base64EncodedString()
var buffer = context.channel.allocator.buffer(capacity: encodedData.count)
buffer.writeString(encodedData)
let outgoingEnvelope = AddressedEnvelope(remoteAddress: incomingEnvelope.remoteAddress, data: buffer)
context.write(wrapOutboundOut(outgoingEnvelope), promise: nil)
print("dubug: send image \(videoCapture.framePos) - \(encodedData.count) bytes")
}
public func channelReadComplete(context: ChannelHandlerContext) {
context.flush()
}
public func errorCaught(context: ChannelHandlerContext, error: Error) {
print("error: ", error)
context.close(promise: nil)
}
}
enum UDPServerError: Error {
case invalidHost
case invalidPort
}
class UDPServer {
private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
private var host: String?
var port: Int?
init(host: String, port: Int) {
self.host = host
self.port = port
}
func start() throws {
guard let host = host else {
throw UDPServerError.invalidHost
}
guard let port = port else {
throw UDPServerError.invalidPort
}
do {
let bootstrap = DatagramBootstrap(group: group)
.channelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
.channelInitializer { channel in
channel.pipeline.addHandler(ClientHandler())
}
let channel = try bootstrap.bind(host: host, port: port).wait()
print("Server started and listening on \(channel.localAddress!)")
} catch let error {
throw error
}
}
func stop() {
do {
try group.syncShutdownGracefully()
} catch let error {
print("Error shutting down \(error.localizedDescription)")
exit(0)
}
print("Client connection closed")
}
}