iOS中的TCP流与调度

iOS中的TCP流与调度,ios,swift,dispatch-async,Ios,Swift,Dispatch Async,我必须建立一个应用程序,也将能够接收和发送数据。 我需要创建至少两个线程。一个可以持续监听和响应接口并发送数据的接口 var a = connectionClass() @IBOutlet weak var textField: UITextField! @IBAction func myButton(sender: AnyObject) { a.sendData() } override func viewDidLoad() { super.viewDidLoad()

我必须建立一个应用程序,也将能够接收和发送数据。 我需要创建至少两个线程。一个可以持续监听和响应接口并发送数据的接口

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")
}
此代码锁定用户界面,但它正在接收数据。 我正在寻找解决方案,或者说例子,在那里我可以看到我的问题的解决方案

为了创建流,我使用了以下代码:

=========================================================================

好了,开始工作了。我可以打开连接并发送数据。 但现在我不知道如何使用其他类的函数来读取流。 如何创建self.a.stream 流(aStream:NSStream,handleEvent事件代码:NSStreamEvent) 从我不知道如何使用event和如何初始化NSString开始。 我知道,这是个愚蠢的问题,但对我来说很复杂

视图控制器: 导入UIKit

类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.
}
}

连接类别: 进口基金会

类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)")

}
override init(){
}
//德克拉拉贾·波德斯塔沃维奇·兹米恩尼奇
私有let服务器地址:CFString=“someIp”
专用let服务器端口:UInt32=10001
私有变量输入流:NSInputStream!
私有变量outputStream:NSOutputStream!
变量i=0
//伊尼贾利扎卡·波希尼亚
func initNetworkCommunication(){
//兹米安·波兹本·波比亚尼亚和维西亚尼亚·达尼奇
var readStream:非托管?
var writeStream:非托管?
//双流
自动释放池{
CFStreamCreatePairWithSocketToHost(nil、self.serverAddress、self.serverPort、readStream和writeStream)
}
self.inputStream=readStream!.takeRetainedValue()
self.outputStream=writeStream!.takeRetainedValue()
//代表团w斯威夫特-doczytać
self.inputStream.delegate=self
self.outputStream.delegate=self
//tworzy pętlędla połączenia-doczytać
self.inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(),格式:NSDefaultRunLoopMode)
self.outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(),格式:NSDefaultRunLoopMode)
self.inputStream.open()
self.outputStream.open()
打印(“Zainicjalizowane”)
}
//我和罗比一起开玩笑。你是不是在开玩笑?
函数流(aStream:NSStream,handleEvent事件代码:NSStreamEvent){
印刷品(“一个笑话流”)
开关事件代码{
案例nsstreamvent.OpenCompleted:
印刷品(“Otwarto połączenie”)
打破
案例nsstreamvent.HasSpaceAvailable:
如果outputStream==aStream{
印刷品(“Połączenie jest gotowe”)
打破
}
案例nsstreamvent.hasbytes可用:
印刷品(“Sąramki”)
如果aStream==inputStream{
变量缓冲区:UInt8=0
瓦伦:Int!
while(inputStream?.hasbytes可用!=nil){
len=inputStream?读取(&缓冲区,最大长度:32)
如果len>0{
让输出=缓冲区
打印(“服务器odpowiedzia:\(输出)”)
}
}
}
打破
发生NSStreamEvent.Error的情况:
印刷品(“Nie można połączyćsięz serwerem!”)
打破
案例NSStreamEvent.EndEncounted:
outputStream.close()
outputStream.removeFromRunLoop(NSRunLoop.currentRunLoop(),格式:NSDefaultRunLoopMode)
outputStream=nil
违约:
印刷品(“Nieznane działanie”)
}
}
func sendData(){
让数据=NSData(字节:[0x0F,0x00,0x10,0x00,0x00,0x80,0x55,0x00,0x55,0x04,0x00,0x01,0x00,0x00,0xB2,0x04]作为[UInt8],长度:16)
outputStream?.write(非安全指针(data.bytes),maxLength:data.length)
打印(“wysłano:\(数据)”)
}
}
首先:不需要线程来执行异步IO。IO可以通过运行循环上的GCD进行调度。这是一个很好的介绍:

第二:我不确定您的
dispatch\u async
code部分想要实现什么。它只是在一个辅助线程中运行
print
。然后你把你的
self.a.initNetworkCommunication
放回到主线程上

第三:查看ChatClientSwift中的代码,
a.sendData()
似乎在执行阻塞写入。那,好吧,街区


有相当多的Swift GCD套接字库可用。这是一个:,还有更多。你可能想看看这种情况。

为什么不使用AFNetworking这样的框架,或者你不能在主线程中发送阻塞网络代码呢?你有没有收到任何错误,或者它只是冻结了?你能提供任何调试信息吗?我正在试图找出你在哪里阻止了主线程。我已经下载了SwiftSockets并试图构建它,但它是用Swift 3之前的Swift版本编写的。我越是试图修改它,无论有没有编辑转换和自动修复,我得到的错误就越多。我对Mac和Swift完全陌生,所以这可能是问题的一部分。无论如何,如果您能推荐一些其他最新的教程和/或结合Swift 3、GCD和TCP套接字的开源项目,我将不胜感激。我一片空白。。。谢谢。在继续我之前的评论时,我现在在GitHub上找到了这个项目:它是最新的(Swift 3,目前每天提交几次),并且为套接字提供了一个纯Swift包装器。它本身并不使用GCD,但在“ReadMe”中有一个测试程序,显示了如何在用Swift编写的调用程序中使用GCD。