2016-06-28 150 views
0

我想建立一个类,可以使用纯Swift代码创建一个TCP连接。一切都编译文件,但是当下面的代码运行时,我调用getaddrinfo函数时发生EXC_BAD_ACCESS崩溃。纯Swift TCP连接

尝试在getaddrinfo函数的最后一个参数中引用servInfo变量时发生崩溃。我查看了网络,看起来我声明UnsafeMutablePointer变量的方式是正确的,因为它需要由getaddrinfo函数设置。

有没有人有任何想法发生了什么?我正在构建使用最新的Swift 3快照。

import Darwin 
import Foundation 

class SwiftTcp { 

    //MARK: - Properties 

    var serviceAddress = "0.0.0.0" 
    var servicePort: Int = 8080 

    //MARK: - Read-only properties 

    private(set) var status: Int32 = 0 

    //MARK: - Private variables 

    // protocol configuration 
    private var hints = addrinfo(
     ai_flags: AI_PASSIVE, 
     ai_family: AF_UNSPEC, 
     ai_socktype: SOCK_STREAM, 
     ai_protocol: 0, 
     ai_addrlen: 0, 
     ai_canonname: nil, 
     ai_addr: nil, 
     ai_next: nil) 

    // used to set the protocol info needed to make a socket connection 
    private var servInfo: UnsafeMutablePointer<addrinfo> = nil 

    //MARK: - Initialization 

    deinit { 
     freeaddrinfo(servInfo) 
    } 

    init() { 

     SwiftLog.trace("[SwiftTcp][Connect] Initialize...") 

     // get protocol info 
     status = getaddrinfo(
      nil, 
      UnsafePointer<Int8>(bitPattern: servicePort), 
      &hints, 
      &servInfo) 

     if (status != 0) { 
      let err = String(UTF8String: gai_strerror(status)) ?? "Unknown error code" 
      SwiftLog.error("Unable to get address information: Error \(err)") 
      return 
     } 

     #if DEBUG 

      var info = servInfo 

      repeat { 

       let (clientIp, service) = sockaddrDescription(info.memory.ai_addr) 
       let message = "HostIp: " + (clientIp ?? "?") + " at port: " + (service ?? "?") 
       SwiftLog.debug(message) 

       // get next or nil 
       info = nil 
       info = info.memory.ai_next 

      } while info != nil 

     #endif 
    } 

    func connect() { 
     // do nothing 
    } 

    //MARK: - Private Helpers 

    private func sockaddrDescription(addr: UnsafePointer<sockaddr>) -> (String?, String?) { 

     var host : String? 
     var service : String? 

     var hostBuffer = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0) 
     var serviceBuffer = [CChar](count: Int(NI_MAXSERV), repeatedValue: 0) 

     if getnameinfo(
      addr, 
      socklen_t(addr.memory.sa_len), 
      &hostBuffer, 
      socklen_t(hostBuffer.count), 
      &serviceBuffer, 
      socklen_t(serviceBuffer.count), 
      NI_NUMERICHOST | NI_NUMERICSERV) 

      == 0 { 

      host = String(UTF8String: hostBuffer) 
      service = String(UTF8String: serviceBuffer) 
     } 
     return (host, service) 

    } 

} 

回答

2

status = getaddrinfo(
     nil, 
     UnsafePointer<Int8>(bitPattern: servicePort), 
     &hints, 
     &servInfo) 

第二种说法是没有意义的,并导致崩溃,因为你是铸造数量8080 的指针。

getaddrinfo()预计此C字符串(UnsafePointer<Int8>在SWIFT), 但你可以简单地传递一个斯威夫特字符串,它是自动 转换(如String value to UnsafePointer<UInt8> function parameter behavior解释):

let servicePort = "8080" 
status = getaddrinfo(
     nil, 
     servicePort, 
     &hints, 
     &servInfo) 
+0

Awesome..that固定我问题。谢谢! –