2016-06-28 5 views
0

순수 스위프트 코드를 사용하여 TCP 연결을 만들 수있는 클래스를 만들려고합니다. 모든 것은 파일을 컴파일하지만 아래 코드가 실행될 때 getaddrinfo 함수를 호출 할 때 EXC_BAD_ACCESS 충돌이 발생합니다.순수 스위프트 TCP 연결

함수의 마지막 매개 변수에서 servInfo 변수를 참조하려고 할 때 충돌이 발생합니다. 나는 웹 주위를 둘러 보았고 그것이 getaddrinfo 함수에 의해 설정 될 필요가 있기 때문에 UnsafeMutablePointer 변수가 정확하다고 선언하는 것처럼 보입니다.

어떤 아이디어가 있습니까? 최신 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>), 을 기대하지만, 당신은 단순히 ( String value to UnsafePointer<UInt8> function parameter behavior에서 설명) 가 자동으로 변환하는 스위프트 문자열을 전달할 수 있습니다

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

Awesome..that 고정을 내 문제. 감사! –