Aug 09, 2021, TIL (Today I Learned) - Streams, Sockets, and Ports

Inwoo Hwang·2021년 8월 26일
0
post-thumbnail

Streams, Sockets, and Ports


Stream

An abstract class representing a stream

class Stream : NSObject

Stream 객체는 디바이스로부터 독립적으로 존재하는 여러가지 미디어로부터 데이터를 읽거나 쓸 수 있는 기능을 제시 해 줍니다. 메모리, 파일, 또는 네트워크(소켓을 활용하여)에 존재하는 데이터를 위한 stream 객체를 생성할 수 있고 해당 데이터를 모두 로딩하지 않아도 stream 객체를 사용할 수 있습니다.

기본적으로, 파일 기반이 아닌 stream 인스턴스들은 일회성 one-way 통신입니다.

Subclassing

NSStream은 추상클래스이기 때문에 직접적으로 해당 클래스를 인스턴스화 하기 보다는 해당 클래스를 상속받아서 활용해야 합니다. 해당 클래스를 상속받은 InputStreamOutputStream 은 프로그래머가 사용할수 있게 적합하게 구현된 애플이 제공하는 대표적인 자식 클래스들입니다. 물론 two-way 스트림 또는 stream을 찾아내는 등 추가 기능을 더하려면 위에 언급한 클래스들을 다시 상속받아야 합니다.

Methods to Override

  • open()close()

open() 을 활용하여 stream을 읽고 쓰고 그리고 클라이언트가 접근할 수 있게 만들 수 있습니다.

close() 를 활용하여 스트림을 종료시키고 run loop로부터 stream 인스턴스를 제거할 수 있습니다. 종료된 stream은 새로운 프로퍼티를 받을 수 있고 자신의 프로퍼티를 알릴 수 있습니다. 다만 stream은 한 번 종료되면 다시 열릴 수 없습니다.

  • delegate

대리자 지정하고 반환합니다. 기본적으로 stream 객체는 자기 자신의 대리자 입니다. 그렇기 때문에 nil을 매개변수로 받아서 전달할 경우 대리자를 다시 복원시킵니다. 참조순환을 방지하기 위해 해당 delegate를 강한 참조로 구현하지 말아야 합니다.

  • schedule(in:forMode:) 그리고 remove(from:forMode:)

schedule() 메서드를 활용하여 스트림 인스턴스를 특정한 모드를 위한 특정한 runloop에 준비시킬 수 있습니다. remove 메서드를 활용하여 stream 객체를 run loop로부터 제거할 수도 있습니다.한 번 stream 인스턴스가 run loop에 스케줄링되면 stream 객체가 stream(_:handle:) 메세지를 자신의 delegate에게 보내게 되고 이는 자식클래스가 책임져야합니다.

  • property(forKey:) 그리고 setProperty(_:forKey:)

해당 메서드를 사용하여 특정 key에 대한 value를 반환하고 세팅할 수 있습니다. 커스텀 프로퍼티 또한 더할 수 있습니다만 NSStream에 정의된 모든 프로퍼티가 잘 처리되는지 확인해야 합니다.

  • streamStatusstreamError

streamStatus르ㄹ 활용하여 stream의 현제 상태를 NSStreamStatus 상수로 반환할 수 있습니다. strea,Error 를 활용하여 현재 에러를 보여주는 NSError 객체를 반환할 수 있습니다.

[출처]:

Apple Developer Document | Stream

InputStream

A Stream that provides read-only stream functionality

class InputStream : Stream

*toll-free bridging: 파라미터로 CoreFoundation과 Foundation class 둘 다 받을 수 있는 것을 뜻합니다.

InputStream은 Core Foundation의 CFReadStream 과 toll-free bridge 되어있습니다.

Subclassing

NSInputStream은 Stream을 상속받는 추상클래스입니다.

InputStream은 stream data의 읽기-전용 접근을 제공하는 클래스입니다.

따라서 stream data에 접근하기 위해서는 해당 클래스를 상속받아서 사용할 수 있습니다.

Methods to Override

InputStream을 생성하기 위해서는 필요한 타입에 해당 되는 initializer를 통해서 초기화 시켜야 합니다. 그리고 아래 메서드를 제공 해 주어야 합니다.

  • read(_:maxLength:)

  • getBuffer(_:length:)

  • hasBytesAvailable

OutputStream

A stream that provides write-only stream functionality.

class OutputStream : Stream

InputStream은 Core Foundation의 CFWriteStream 과 toll-free bridge 되어있습니다.

Subclassing

NSOutputStream은 Stream을 상속받는 추상클래스입니다.

OutputStream은 stream data의 쓰기-전용 접근을 제공하는 클래스입니다.

Methods to Override

OutputStream을 생성하기 위해서는 필요한 타입에 해당 되는 initializer를 통해서 초기화 시켜야 합니다. 그리고 아래 메서드를 제공 해 주어야 합니다.

  • write(_: maxLenth:)
  • hasSpaceAvailable

[출처]:

Apple Developer Document | OutputStream

Stream Delegate

An interface that delegates of a stream instance use to handle events on the stream

protocol StreamDelegate
func stream(_ aStream: Stream, handle eventCode: Stream.Event)

The delegate receives this message when a given event has occurred on a given stream.

Parameters

theStream

  • 스트림 이벤트가 일어난 스트림

streamEvent

  • 스트림 이벤트

Discussion

대리자는 theStream이 run loop에 예정될 때 대리자는 메세지를 보냅니다. 메세지는 stream의 객체의 쓰레드에게 전달이 됩니다. 대리자는 streamEvent 를 검토하여 적절한 행동을 취해야 합니다.

[출처]:

Apple Developer Document | Stream Delegate

Apple Developer Document | stream(_:handle:)


Sockets

Port

An abstract class that represents a communication channel.

class Port : NSObject

Overview

일반적으로 다른 쓰레드 또는 task 에 있는 Port 객체간에는 소통이 일어납니다. Port 객체를 활용하여 여러 군데 헡어진 객체들은 PortMessage 객체들을 활용하여 소통을 할 수 있습니다. Port 객체를 활용한 소통은 꼭 필요할 때만 사용되어야 합니다.

Port message를 받기 위해서는 Port 객체를 runLoop 객체에 input source로 추가해야 합니다. NSConnection 객체들은 자동으로 초기화 시점에서 port를 추가합니다.

Port 객체가 port message를 받으면 이 매세지를 자신의 delegate에게 전달합니다[handleMachMessage(_:) or handle(_:) message]. delegate는 이 메서드 중 상황에 따른 적합한 메서드를 하나 골라서 사용해야 합니다.

MachMessage는 메세지를 가공되지 않은 msg_header_t struct로 시작하는 Mach message를 전달 해 주는 메서드입니다.

handle은 PortMessage의 인스턴스의 형태로 메세지를 제공합니다.

만약 delegate가 존재하지 않는다면 NSPort 객체가 메세지를 직접적으로 처리합니다.

port 객체 사용이 끝나면 release message를 보내기 전에 port 객체를 확실하게 메모리에서 해제해야 합니다. 그렇지 않으면 메모리 누수를 야기할 수 있습니다. 해당 작업을 하기 위해서 invalidate() 메서드를 호출해야 합니다.

Foundation은 NSPort의 3가지 자식클래스를 정의합니다. NSMachPort 그리고 MessagePort 는 로컬영역(기기 내부)의 소통을 지원합니다. SocketPort 는 반면에 로컬 그리고 원격 소통(Network)을 지원합니다.

Apple Developer Document | Port

profile
james, the enthusiastic developer

0개의 댓글