在 Swift 中使用 NSStream 连接到 Redis 服务器

Connecting to Redis server with NSStream in Swift

大家好,正如标题提到的,我正在尝试使用 swift 语言从我的 Redis 服务器发送和接收数据。我做了很多研究,但我无法找到关于这个主题的好答案,我最接近的是 NSStream 或一些 Github 项目(其中大多数代码有问题),我已经尝试创建一个解决方案 3 天了,请有人帮忙。

Redis 端口 6379 的连接要求:

问题:

  1. App Delegate 崩溃线程 1:EXC_BAD_ACCESS(code=1, address=XXXXXXXX)有时
  2. 无数据return

Class 带初始化 (Redis): 最接近我可以达到的水平,我可以理解 NSStream 的过程,但是这不会在我的对话框中为 return 打印任何内容,我可以搞不懂怎么回事。

class Redis: NSObject, NSStreamDelegate {

     //Intilizing Stream & Requirement
     var endPoint: CFString?
     var onPort: UInt32?
     var inputStream: NSInputStream?
     var outputStream: NSOutputStream?

服务器连接函数:

    func serverConnection(endPoint: CFString, onPort: UInt32){

        //Streams Init
        let Host: CFString = endPoint
        let Port: UInt32 = onPort
        var readStream: Unmanaged<CFReadStream>?
        var writeStream: Unmanaged<CFWriteStream>?

        //Bind Streams to Host and Port
        CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, Host, Port, &readStream, &writeStream)

        //Cast CFStream to NSStreams
        inputStream = readStream!.takeRetainedValue()
        outputStream = writeStream!.takeRetainedValue()

        //Assign Delegate
        inputStream!.delegate = self
        outputStream!.delegate = self

        //Schadule Run-loop
        inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
        outputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)

        //Open Connection
        inputStream!.open()
        outputStream!.open()


    }

Stream: 应用程序午餐后我收到应用程序委托错误 SOMETIMES

Thread 1: EXC_BAD_ACCESS(code=1, address=XXXXXXXX)

    func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
        if aStream === inputStream {
            switch eventCode {
            case NSStreamEvent.ErrorOccurred:
                //Print Available Errors
                print("Error: \(aStream.streamError?.description)")
                break
            case NSStreamEvent.OpenCompleted:
                //Connection Succeed
                print("Connection Complete \(aStream.description)")
                break
            case NSStreamEvent.HasBytesAvailable:
                //Server Respond
                var buffer = [UInt8](count: 8, repeatedValue: 0)
                while inputStream?.hasBytesAvailable != nil {
                    let result: Int = (inputStream?.read(&buffer, maxLength: buffer.count))!
                    print(result)
                    print(buffer)
                }
                break
            default:
                break

            }
        }

        if aStream === outputStream {
            switch eventCode {
            case NSStreamEvent.ErrorOccurred:
                //Print Available Errors
                print("Error: \(aStream.streamError?.description)")
                break
            case NSStreamEvent.OpenCompleted:
                //Connection Succeed
                print("Connection Complete \(aStream.description)")
                break
            case NSStreamEvent.HasSpaceAvailable:
                //Ready to Send more Dat
                print("HasSpaceAvailable \(aStream.description)")
                break
            default:
                break

            }
        }

    }

Server Test with Ping: return 应该是 PONG

func Ping(){
    let Command: NSString = NSString(format: "Ping /n", String(endPoint))
    let data: NSData = NSData(data: Command.dataUsingEncoding(NSUTF8StringEncoding)!)
    outputStream!.write(UnsafePointer<UInt8>(data.bytes), maxLength: data.length)
}

如果有人有兴趣下载,感谢 GCDAsyncSocket, I was able to create a solution for Redis connection with Swift 2. I'm also working on Full set Framework on Github for Redis。

Redis Class:你必须包括GCDAsyncSocketDelegate

import Foundation
class Redis: NSObject,  GCDAsyncSocketDelegate {

    //Alloc GCDAsyncSocket
    var Socket: GCDAsyncSocket?

    /*============================================================
    // Server Open Connection
    ============================================================*/
    func server(endPoint: String, onPort: UInt16){

        //Check For Socket Condition
        if !(Socket != nil) {

            //Assign Delegeate to Self Queue
            Socket = GCDAsyncSocket(delegate: self, delegateQueue: dispatch_get_main_queue())

        }

        var err: NSError?

        /*============================================================
        GCDAsyncSocket ConnectToHost Throw Error so you must handle 
        this with Try [Try!], do, Catch.
        ============================================================*/

        do{
            //Assign Function Constants
            try Socket!.connectToHost(endPoint, onPort: onPort)
        }catch {
            //Error
            print(err)
        }

        //Read Send Data
        Socket?.readDataWithTimeout(2, tag: 1)
    }


    //Server Confirmation
    func socket(sock: GCDAsyncSocket!, didConnectToHost host: String!, port: UInt16) {
        print("Connected to Redis!")
    }

    /*============================================================
    // Read Data From Redis Server [NSUTF8StringEncoding]
    ============================================================*/

    func socket(sock: GCDAsyncSocket!, didReadData data: NSData!, withTag tag: Int) {
        let Recieved: NSString = NSString(data: data, encoding: NSUTF8StringEncoding)!
        print(Recieved)
    }

    /*===============================================================
    // Send Command [I Will create Full SET and Upload it to Github]
    =================================================================*/

    func Command(Command: String){
        let request: String = Command + "\r\n"
        let data: NSData = request.dataUsingEncoding(NSUTF8StringEncoding)!
        Socket!.writeData(data, withTimeout: 1.0, tag: 0)

    }

}

通过创建 class Redis 常量来调用方法

 let redisServer = Redis()
 redisServer.server("XX.XX.XXX.XXX", onPort: 6379)
 redisServer.Command("Ping") //Return Should be **PONG**