3

我正在尝试使用 Swift2.1.1 中的 Xcode:7.2.1 为 Mac OSX 编写套接字服务器应用程序。参考CocoaEcho 示例代码。但是我不能在 socketCallBack 函数中调用 swift 函数。
我的代码在这里。我根据Swift 2 - UnsafeMutablePointer 的答案将 self 传递给 object。而且我认为代码的一部分工作正常。

class myServer: NSObject {

  // sockets
  private var socketipv4: CFSocket!
  private var socketipv6: CFSocket!

  // Connections
  var connections = Set<SPFConnection>()

  func start(address: String) -> Bool {

    var sockCtxt = CFSocketContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
    sockCtxt.info = UnsafeMutablePointer(unsafeAddressOf(self))

    // create socket with CFSocketCreate
    socketipv4 = CFSocketCreate(
        kCFAllocatorDefault,
        PF_INET,
        SOCK_STREAM,
        IPPROTO_TCP,
        kCFSocketAutomaticallyReenableAcceptCallBack,
        socketCallBack,
        &sockCtxt)

    // ipv4
    var sin = sockaddr_in()  // = initStruct()
    let server_addr_size = socklen_t(INET_ADDRSTRLEN)
    sin.sin_len = UInt8(server_addr_size)
    sin.sin_family = sa_family_t(AF_INET)
    sin.sin_port = UInt16(9999).bigEndian
    sin.sin_addr.s_addr = inet_addr(address)

    let sinData = NSData(bytes: &sin, length: sizeof(sockaddr_in))
    let ptr = UnsafePointer<UInt8>(sinData.bytes)

    let sincfd = CFDataCreate(kCFAllocatorDefault, ptr, sizeof(sockaddr_in))

    let ipv4SocketError: CFSocketError = CFSocketSetAddress(socketipv4, sincfd)
    switch ipv4SocketError {
    case .Success:
        print("ipv4 Success")
    default:
        print("ipv4 error = \(ipv4SocketError.rawValue)")
        return false
    }

    let socketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socketipv4, 0)
    CFRunLoopAddSource(CFRunLoopGetCurrent(), socketSource, kCFRunLoopDefaultMode)

    return true
  }

  // CFSocket call back
  var socketCallBack : @convention(c)(CFSocket!, CFSocketCallBackType, CFData!, UnsafePointer<Void>, UnsafeMutablePointer<Void>) -> Void = {
    (socketRef, callbackType, address, data, info) in

    print("acceptConnection callback-ed") // \(socketRef), \(callbackType), \(address), \(data),\(info)")

    var tempData: CFSocketNativeHandle = 0
    var anNSData:NSData = NSData(bytes: data, length: sizeofValue(data))
    anNSData.getBytes(&tempData, length: sizeof(CFSocketNativeHandle))

    var tempAry = [UnsafeMutablePointer<Void>]()
    tempAry.append(info)
    if callbackType == CFSocketCallBackType.AcceptCallBack {
        let server = unsafeBitCast(info, myServer.self)
        // **** EXEC_BAD_ACCESS, code=2 ***** //
        server.acceptConnection(tempData)
    } else {
        print("callbacktype = \(callbackType.rawValue)")
    }
  }


  func acceptConnection(data: CFSocketNativeHandle) {
    print("acceptConnection called")
    var readStream: Unmanaged<CFReadStream>?
    var writeStream: Unmanaged<CFWriteStream>?

    CFStreamCreatePairWithSocket(kCFAllocatorDefault, data, &readStream, &writeStream)
    if readStream != nil && writeStream != nil {
        CFReadStreamSetProperty(readStream!.takeUnretainedValue(), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue)
        CFWriteStreamSetProperty(writeStream!.takeUnretainedValue(), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue)

        let connection = SPFConnection()
        connection.inputStream = readStream!.takeRetainedValue()
        connection.outputStream = writeStream!.takeRetainedValue()

        if connection.open() {
            connections.insert(connection)
        }
    }
  }
}

我在代码server.acceptConnection(tempData)处得到 EXEC_BAD_ACCESS code=2 。
调试器为infoserver显示相同的指针,这应该意味着info(self)已正确分配给server。但 EXEC_BAD_ACCESS 似乎意味着 self 不再可用。我正在努力寻找解决方案。如果有人能给我任何建议,将不胜感激。在此先感谢您的帮助。

4

1 回答 1

0

我承认我对使用这些较低级别的 C 约定知之甚少,但是由于回调函数是您的类的一部分,所以不能只说 self.acceptConnection(tempData) 吗?

于 2016-02-06T03:03:16.130 回答