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

Far*_*had 9 sockets nsstream redis ios swift

大家好,标题提到我正试图用快速语言从我的Redis服务器发送和接收数据.我已经做了很多研究,我无法得到关于这个主题的好答案,我最接近的是NSStream或几个Github项目(其中大部分都有破碎的代码),我一直试图为3创建一个解决方案几天了,请有人帮忙.

端口6379Redis的连接要求:

  • TCP
  • Telnet(我最喜欢的)

问题:

  1. App Delegate Crash Thread 1:EXC_BAD_ACCESS(code=1, address=XXXXXXXX) SOMETIMES
  2. 没有数据返回

具有初始化的类(Redis): 最接近我可以达到我理解NSStream的过程的级别,但是再次在我的对话框中没有打印任何返回的内容,我无法弄清楚出了什么问题.

class Redis: NSObject, NSStreamDelegate {

     //Intilizing Stream & Requirement
     var endPoint: CFString?
     var onPort: UInt32?
     var inputStream: NSInputStream?
     var outputStream: NSOutputStream?
Run Code Online (Sandbox Code Playgroud)

服务器连接功能:

    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()


    }
Run Code Online (Sandbox Code Playgroud)

流:一旦应用程序的午餐,我得到一个应用程序委托错误SOMETIMES

线程1:EXC_BAD_ACCESS(代码= 1,地址= 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

            }
        }

    }
Run Code Online (Sandbox Code Playgroud)

使用Ping进行服务器测试:返回应为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)
}
Run Code Online (Sandbox Code Playgroud)

Far*_*had 3

感谢GCDAsyncSocket,我能够为 Redis 与Swift 2连接创建一个解决方案。如果有人有兴趣下载,我还在Github上开发Redis 的全套框架。

Redis类:您必须包含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)

    }

}
Run Code Online (Sandbox Code Playgroud)

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

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