在 Swift 中使用 NSStream 连接到 Redis 服务器
Connecting to Redis server with NSStream in Swift
大家好,正如标题提到的,我正在尝试使用 swift 语言从我的 Redis 服务器发送和接收数据。我做了很多研究,但我无法找到关于这个主题的好答案,我最接近的是 NSStream
或一些 Github 项目(其中大多数代码有问题),我已经尝试创建一个解决方案 3 天了,请有人帮忙。
Redis 端口 6379 的连接要求:
- TCP
- Telnet(我的最爱)
问题:
- App Delegate 崩溃线程 1:
EXC_BAD_ACCESS(code=1, address=XXXXXXXX)
有时
- 无数据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**
大家好,正如标题提到的,我正在尝试使用 swift 语言从我的 Redis 服务器发送和接收数据。我做了很多研究,但我无法找到关于这个主题的好答案,我最接近的是 NSStream
或一些 Github 项目(其中大多数代码有问题),我已经尝试创建一个解决方案 3 天了,请有人帮忙。
Redis 端口 6379 的连接要求:
- TCP
- Telnet(我的最爱)
问题:
- App Delegate 崩溃线程 1:
EXC_BAD_ACCESS(code=1, address=XXXXXXXX)
有时 - 无数据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**