美文网首页
SwiftNIO-连接Redis(一)

SwiftNIO-连接Redis(一)

作者: 小天枢丶 | 来源:发表于2018-06-14 10:02 被阅读0次

    上星期用SwiftNIO写了一套程序,然后需要用到redis做缓存,然后就去GitHub上找了一下发现有一个开源库,但是用的时候发现有Bug,向作者提了issue之后至今没有修复... 所以就自己动手造了个轮子,顺便学习一下。

    要做redis客户端的话有两个东西必须要了解,RESP协议redis命令

    简单介绍RESP

    • 单行字符串(Simple Strings), 开头字符为:'+' "+OK\r\n"
    • 错误信息(Errors),开头字符为:'-' "-Error message\r\n"
    • 整形数字(Integers),开头字符为:':' ":0\r\n"
    • 多行字符串(Bulk Strings),开头字符为:'$' "$6\r\nfoobar\r\n"
    • 数组(Arrays),开头字符为:'*' "*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"

    需要注意的是不管是发送的命令还是收到来自redis服务端的回复,都是以\r\n结尾。

    Java那边的叫Jedis,用Netty写的叫Nedis,那么我就把这个命名为Sedis了!

    首先创建一个struct,用来存储连接信息:

    struct SedisOptions {
        let prot: Int
        let host: String
        var password: String?
        var database: Int?
    }
    

    然后创建SedisClient类:

    这个类里面需要根据SedisOptions的信息来创建连接,包括身份验证。

    class SedisClient {
        private let options: SedisOptions
        private var bootstrap: ClientBootstrap?
        private var loopGroup: EventLoopGroup!
        
        init(options: SedisOptions) {
            self.options = options
            
            loopGroup = MultiThreadedEventLoopGroup(numThreads: System.coreCount)
            bootstrap = ClientBootstrap(group: loopGroup)
                .channelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET),
                                                     SO_REUSEADDR), value: 1)
                .channelInitializer({ (channel) -> EventLoopFuture<Void> in
                        channel.pipeline.add(handler: RESPHandler())
                })
            
        }
        
        private func _connect() -> EventLoopFuture<Channel> {
            assert(bootstrap != nil, "init failure")
            
            return bootstrap!.connect(host: options.host, port: options.prot)
        }
    }
    

    之前写了一遍用SwiftNIO建立UDP通讯的,用的是DatagramBootstrap,我们这里需要当作客户端连接,所以用的是ClientBootstrap

    最后加上一个RESPHandler

    class RESPHandler: ChannelDuplexHandler {
        typealias InboundIn = ByteBuffer
        
        func channelRead(ctx: ChannelHandlerContext, data: NIOAny) {
            var value = unwrapInboundIn(data)
            print(value.readString(length: value.writerIndex))
        }
    }
    

    这里接收到服务端回复后先不做任何操作直接输出。

    现在在SedisClientinit方法末尾加上一段测试代码测试是否能正常通讯

    init(options: SedisOptions) {
            self.options = options
            
            loopGroup = MultiThreadedEventLoopGroup(numThreads: System.coreCount)
            bootstrap = ClientBootstrap(group: loopGroup)
                .channelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET),
                                                     SO_REUSEADDR), value: 1)
                .channelInitializer({ (channel) -> EventLoopFuture<Void> in
                        channel.pipeline.add(handler: RESPHandler())
                })
            
            let channel = try? _connect().wait()
            let command = "set a 1\r\n".utf8
            var byteBuffer = ByteBufferAllocator().buffer(capacity: command.count)
            byteBuffer.write(bytes: command)
            channel?.writeAndFlush(byteBuffer, promise: nil)
            try? channel?.closeFuture.wait()
        }
    
    

    测试运行

    let sdies = SedisClient(options: SedisOptions(prot: 6379, host: "127.0.0.1", password: nil, database: 0))
    

    可以看到控制台输出

    Optional("+OK\r\n")
    

    至此,第一部分就已经finish

    相关文章

      网友评论

          本文标题:SwiftNIO-连接Redis(一)

          本文链接:https://www.haomeiwen.com/subject/wvmeeftx.html