SwiftNIO-连接Redis(一)

上星期用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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 职场中,拥有好人缘,有助于平日办公,甚至是升职。相反,如果同事都不喜欢与你相处,你在职场中将步履维艰。想受同事欢迎...
    哈默老师阅读 391评论 0 0
  • 上一期讲了第一阶段---移情。在移情阶段完成后,你就要进入黏性阶段,这个阶段你需要思考的重点就落在了产品留存率上,...
    Katrina程阅读 425评论 0 0
  • 今个真真的是文思泉涌啊~~~噗! 好吧,算是补档生日那天,恩,没错,还账。 现在已经23了(吧~93生,各位看官帮...
    lorraineldan阅读 278评论 0 1
  • 月亮为什么有时是船,有时是圆? 妈妈笑了,她说因为月亮和你一样淘气 爸爸为什么会长胡子? 爸爸笑了,他说因为头发迷...
    广电1702李汇阳22阅读 183评论 0 3