iOS

CFSocket을 통한 로컬 서버 만들기 2

스엠 2023. 6. 26. 22:22

전글에서 setsocketopt()의 함수를 통해서 생성한 소켓의 옵션까지 정하는 것을 했습니다.

계속 이어서 이번에는 socket의 주소를 설정하는 법을 알아보겠습니다.

 

우선 코드 부터 보겠습니다.

var addr = sockaddr_in(sin_len: __uint8_t(MemoryLayout<sockaddr_in>.size),
                               sin_family: sa_family_t(AF_INET),
                               sin_port: port.bigEndian,
                               sin_addr: in_addr(s_addr: INADDR_ANY),
                               sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        
        let addrData = withUnsafePointer(to: &addr) { ptr in
            return ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) { addrPtr in
                return Data(bytes: addrPtr, count: MemoryLayout<sockaddr_in>.size)
            }
        }
       
        let result = CFSocketSetAddress(sock!, addrData as CFData)
        guard result == .success else {
            throw SocketError.SocketBindingFailed
        }

 

 

우선 sockaddr_in 부터 살펴보겠습니다.
sockaddr_in의 경우 리눅스 기반의 os에서 소켓의 주소를 설정하기 위해서 공용적으로 쓰이는 구조체 입니다.
특히 소켓의 family가 AF_INET으로 설정된 경우에 사용됩니다.
각 인자별 설명은 다음과 같습니다.

var addr = sockaddr_in(sin_len: 구조체의 길이,
                               sin_family: 주소 패밀리 설정 거의 AF_INET으로 고정,
                               sin_port: port번로 bigEndian으로 설정,
                               sin_addr: IPv4 구조체로 주로 in_addr(s_addr: INADDR_ANY) 설정 하는데 
INADDR_ANY의 경우 0.0.0.0의 주소를 나타내고 즉 들어오는 연결을 거르지 않고 수신하겠다는 의미,
                               sin_zero: swift에서는 사용되지 않는 패딩)

 

다음 코드로 넘어가겠습니다. 

        let addrData = withUnsafePointer(to: &addr) { ptr in
            return ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) { addrPtr in
                return Data(bytes: addrPtr, count: MemoryLayout<sockaddr_in>.size)
            }
        }

위 의 코드의 경우 sockaddr_in의 구조체를 사용했을때 이것을 Data형식으로 바꾸는 과정입니다.
1. withUnsafePointer를 사용하여 sockaddr_in의 주소값을 가져오고 
2. ptr.withMemoryRebound()를 사용하여 sockaddr_in의 구조체를 sockaddr로 치환합니다.
3. addrPtr와 Data(bytes:,count:)생성자를 통하여 이것을 Data로 변환합니다.

그리고 마지막으로 다음 코드를 통해서 소켓의 주소를 할당합니다.

        let result = CFSocketSetAddress(sock!, addrData as CFData)
        guard result == .success else {
            throw SocketError.SocketBindingFailed
        }

여기까지가 기본적인 서버사이드 소켓의 생성 하는 방법이었습니다.

다음 글에서는 Client단의 소켓을 만드는 방법에 대해서 글을 이어가겠습니다.