iOS 中的 TCP 流和调度
TCP Stream and dispatch in iOS
我必须构建一个能够接收和发送数据的应用程序。
我需要至少创建两个线程。一个是持续监听和响应接口并发送数据。
var a = connectionClass()
@IBOutlet weak var textField: UITextField!
@IBAction func myButton(sender: AnyObject) {
a.sendData()
}
override func viewDidLoad() {
super.viewDidLoad()
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0), { ()->() in
print("gcd hello")
dispatch_async(dispatch_get_main_queue(), {
self.a.initNetworkCommunication()
print("hello from UI thread executed as dispatch")
})
})
print("hello from UI thread")
}
此代码锁定了用户界面,但它正在接收数据。
我正在寻找解决方案,或者例如,在哪里可以找到我的问题的解决方案。
为了创建流,我使用了此处的代码:https://github.com/troligtvis/SwiftChatClient/blob/master/ChatClientSwift/ViewController.swift?
============================================= ============================
好的,它正在运行。我可以打开连接并发送数据。
但是现在我不知道如何使用其他 class 的函数来读取流。
如何创建 self.a.stream
流(aStream:NSStream,handleEvent eventCode:NSStreamEvent)
从那时起我不知道如何使用事件以及如何为 aString 初始化 NSString。
我知道,这是个愚蠢的问题,但对我来说这很复杂。
视图控制器:
导入 UIKit
class ViewController: UIViewController, NSStreamDelegate{
var a = connectionClass()
@IBOutlet weak var textField: UITextField!
@IBAction func myButton(sender: AnyObject) {
a.sendData()
}
override func viewDidLoad() {
super.viewDidLoad()
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), { ()->() in
print("Inicjalizowanie")
self.a.initNetworkCommunication()
dispatch_async(dispatch_get_main_queue(), {
print("hello from UI thread executed as dispatch")
})
})
print("hello from UI thread")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
连接class:
进口基金会
class connectionClass: NSObject, NSStreamDelegate {
override init(){
}
//deklaracja podstawowych zmiennych
private let serverAddress: CFString = "someIp"
private let serverPort: UInt32 = 10001
private var inputStream: NSInputStream!
private var outputStream: NSOutputStream!
var i = 0
//Inicjalizacja połączenia
func initNetworkCommunication() {
//zmienne potrzebne do pobierania i wysyłania danych
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
//tworzy stream
autoreleasepool {
CFStreamCreatePairWithSocketToHost(nil, self.serverAddress, self.serverPort, &readStream, &writeStream)
}
self.inputStream = readStream!.takeRetainedValue()
self.outputStream = writeStream!.takeRetainedValue()
//delegaty w SWIFT - doczytać
self.inputStream.delegate = self
self.outputStream.delegate = self
//tworzy pętlę dla połączenia - doczytać
self.inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.inputStream.open()
self.outputStream.open()
print("Zainicjalizowane")
}
//co ta funkcja robi i gdzie jest używana. Czy ona oczekuje na wywołanie połączenia z serwerem?
func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
print("a tu jest stream")
switch eventCode{
case NSStreamEvent.OpenCompleted:
print("Otwarto połączenie")
break
case NSStreamEvent.HasSpaceAvailable:
if outputStream == aStream{
print("Połączenie jest gotowe")
break
}
case NSStreamEvent.HasBytesAvailable:
print("Są ramki")
if aStream == inputStream{
var buffer: UInt8 = 0
var len: Int!
while (inputStream?.hasBytesAvailable != nil) {
len = inputStream?.read(&buffer, maxLength: 32)
if len > 0 {
let output = buffer
print("Server odpowiedział: \(output)")
}
}
}
break
case NSStreamEvent.ErrorOccurred:
print("Nie można połączyć się z serwerem!")
break
case NSStreamEvent.EndEncountered:
outputStream.close()
outputStream.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
outputStream = nil
default:
print("Nieznane działanie ")
}
}
func sendData() {
let data = NSData(bytes: [0x0F, 0x00, 0x10, 0x00, 0x00, 0x80, 0x55, 0x00, 0x55, 0x04, 0x00, 0x01, 0x00, 0x00, 0xB2, 0x04 ] as [UInt8], length: 16)
outputStream?.write(UnsafePointer<UInt8>(data.bytes) , maxLength: data.length)
print("wysłano: \(data)")
}
}
第一:您不需要线程来执行异步 IO。 IO 可以通过运行循环上的 GCD 进行调度。这是一个很好的介绍:What's New in GCD.
其次:我不确定您尝试使用 dispatch_async
代码部分完成什么。它只是在辅助线程中运行 print
。然后你把你的 self.a.initNetworkCommunication
放回主线程 ...
第三:查看来自 ChatClientSwift 的代码 - a.sendData()
似乎进行了阻塞写入。哪个,嗯,块...
有很多 Swift GCD 套接字库可用。这是一个:SwiftSockets,还有更多。你可能想看看这样的。
我必须构建一个能够接收和发送数据的应用程序。 我需要至少创建两个线程。一个是持续监听和响应接口并发送数据。
var a = connectionClass()
@IBOutlet weak var textField: UITextField!
@IBAction func myButton(sender: AnyObject) {
a.sendData()
}
override func viewDidLoad() {
super.viewDidLoad()
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0), { ()->() in
print("gcd hello")
dispatch_async(dispatch_get_main_queue(), {
self.a.initNetworkCommunication()
print("hello from UI thread executed as dispatch")
})
})
print("hello from UI thread")
}
此代码锁定了用户界面,但它正在接收数据。 我正在寻找解决方案,或者例如,在哪里可以找到我的问题的解决方案。
为了创建流,我使用了此处的代码:https://github.com/troligtvis/SwiftChatClient/blob/master/ChatClientSwift/ViewController.swift?
============================================= ============================
好的,它正在运行。我可以打开连接并发送数据。 但是现在我不知道如何使用其他 class 的函数来读取流。 如何创建 self.a.stream 流(aStream:NSStream,handleEvent eventCode:NSStreamEvent) 从那时起我不知道如何使用事件以及如何为 aString 初始化 NSString。 我知道,这是个愚蠢的问题,但对我来说这很复杂。
视图控制器: 导入 UIKit
class ViewController: UIViewController, NSStreamDelegate{
var a = connectionClass()
@IBOutlet weak var textField: UITextField!
@IBAction func myButton(sender: AnyObject) {
a.sendData()
}
override func viewDidLoad() {
super.viewDidLoad()
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), { ()->() in
print("Inicjalizowanie")
self.a.initNetworkCommunication()
dispatch_async(dispatch_get_main_queue(), {
print("hello from UI thread executed as dispatch")
})
})
print("hello from UI thread")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
连接class: 进口基金会
class connectionClass: NSObject, NSStreamDelegate {
override init(){
}
//deklaracja podstawowych zmiennych
private let serverAddress: CFString = "someIp"
private let serverPort: UInt32 = 10001
private var inputStream: NSInputStream!
private var outputStream: NSOutputStream!
var i = 0
//Inicjalizacja połączenia
func initNetworkCommunication() {
//zmienne potrzebne do pobierania i wysyłania danych
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
//tworzy stream
autoreleasepool {
CFStreamCreatePairWithSocketToHost(nil, self.serverAddress, self.serverPort, &readStream, &writeStream)
}
self.inputStream = readStream!.takeRetainedValue()
self.outputStream = writeStream!.takeRetainedValue()
//delegaty w SWIFT - doczytać
self.inputStream.delegate = self
self.outputStream.delegate = self
//tworzy pętlę dla połączenia - doczytać
self.inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
self.inputStream.open()
self.outputStream.open()
print("Zainicjalizowane")
}
//co ta funkcja robi i gdzie jest używana. Czy ona oczekuje na wywołanie połączenia z serwerem?
func stream(aStream: NSStream, handleEvent eventCode: NSStreamEvent) {
print("a tu jest stream")
switch eventCode{
case NSStreamEvent.OpenCompleted:
print("Otwarto połączenie")
break
case NSStreamEvent.HasSpaceAvailable:
if outputStream == aStream{
print("Połączenie jest gotowe")
break
}
case NSStreamEvent.HasBytesAvailable:
print("Są ramki")
if aStream == inputStream{
var buffer: UInt8 = 0
var len: Int!
while (inputStream?.hasBytesAvailable != nil) {
len = inputStream?.read(&buffer, maxLength: 32)
if len > 0 {
let output = buffer
print("Server odpowiedział: \(output)")
}
}
}
break
case NSStreamEvent.ErrorOccurred:
print("Nie można połączyć się z serwerem!")
break
case NSStreamEvent.EndEncountered:
outputStream.close()
outputStream.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
outputStream = nil
default:
print("Nieznane działanie ")
}
}
func sendData() {
let data = NSData(bytes: [0x0F, 0x00, 0x10, 0x00, 0x00, 0x80, 0x55, 0x00, 0x55, 0x04, 0x00, 0x01, 0x00, 0x00, 0xB2, 0x04 ] as [UInt8], length: 16)
outputStream?.write(UnsafePointer<UInt8>(data.bytes) , maxLength: data.length)
print("wysłano: \(data)")
}
}
第一:您不需要线程来执行异步 IO。 IO 可以通过运行循环上的 GCD 进行调度。这是一个很好的介绍:What's New in GCD.
其次:我不确定您尝试使用 dispatch_async
代码部分完成什么。它只是在辅助线程中运行 print
。然后你把你的 self.a.initNetworkCommunication
放回主线程 ...
第三:查看来自 ChatClientSwift 的代码 - a.sendData()
似乎进行了阻塞写入。哪个,嗯,块...
有很多 Swift GCD 套接字库可用。这是一个:SwiftSockets,还有更多。你可能想看看这样的。