관리 메뉴

HAMA 블로그

스위프트로 TCP 소켓을 다루어보자 [번역] 본문

아이폰 (IOS)

스위프트로 TCP 소켓을 다루어보자 [번역]

[하마] 이승현 (wowlsh93@gmail.com) 2016. 11. 17. 18:25

http://dev.iachieved.it/iachievedit/tcp-sockets-with-swift-on-linux/원본  
(구글번역기로 번역했습니다. 아~주 약간 다듬었을뿐입니다. 엄청나게 발전했군요.) 


TCP Sockets with Swift on Linux

먼 옛날 은하계에서 멀리 떨어져있는 소프트웨어 개발자들은 TCP / IP 소켓으로 클라이언트 - 서버 애플리케이션을 작성했었습니다. 그것은 어둠의 시대 이전, HTTP 이전이었지요.

물론 농담입니다. HTTP는 다양한 클라이언트 - 서버 응용 프로그램을 제공하기 위해 활용 될 수 있으며 REST 응용 프로그램의 기반에 있습니다.  HTTP 가 테이블에 가져오는것은  와이어상에서 패킷을 직접가져오는 작업은 아니지만  합의 된 프로토콜 구조 (그리고 어느 포트가 사용되는지에 대한 표준에 어느 정도의 차이가 있음) 는 패킷에 대한 것입니다.  GET, POST, PUT 등과 같은 동작 동사와 HTTP 헤더 자체가 클라이언트 - 서버 응용 프로그램을 개발하는 데 HTTP 를 이상적으로 만들어 줍니다.

결국 스택 맨 아래에서 운영 체제의 소켓 인터페이스를 통해 비트와 바이트가 마샬링됩니다. 네트워크 소켓과 상호 작용하기 위한 API는 매우 풍부하며 이 주제에 대한 많은 자습서와 서적이 있습니다. C의 IP 네트워킹 루틴은 상당히 장황 할 수 있으며 C ++로 객체 지향 루틴에 캡슐화 된 최초의 "실제"API 중 하나였습니다. 그 전통은 Foundation의 CFStream 클래스와 이제는 Swift  swiftysockets  API로 이어졌습니다.

Swiftychat

Swift에서 TCP / IP 네트워크 소켓을 사용하는 방법을 설명하기 위해 기본 "채팅 시스템" 응용 프로그램 인 Swiftychat 을 개발할 것입니다. 기능면에서 제한적이며 실제로 사용하기에 별다른 의미는 없지만 Swift의 TCP / IP 소켓에서 문자열을 보내고받는 방법의 실제 예입니다.

swiftysockets

Swiftychat는 원래 Zewo 팀이 개발 한 Swift Package Manager-ready TCP / IP 소켓 구현 인 swiftysockets를 사용합니다. 불행히도 패키징 제약으로 인해 우리 시스템에 기본 C 라이브러리 Tide를 설치하기 위해 먼저 약간의 난리법석을 떨어야 합니다. 그럼 이제 해보죠.

$ git clone https://github.com/iachievedit/Tide
Cloning into 'Tide'...
...
$ cd Tide
$ sudo make install
clang -c Tide/tcp.c Tide/ip.c Tide/utils.c
ar -rcs libtide.a *.o
rm *.o
mkdir -p tide/usr/local/lib
mkdir -p tide/usr/local/include/tide
cp Tide/tcp.h Tide/ip.h Tide/utils.h Tide/tide_swift.h tide/usr/local/include/tide
# copy .a
cp libtide.a tide/usr/local/lib/
mkdir -p /usr/local
cp -r tide/usr/local/* /usr/local/

어떤 시점에서 우리는 Swift Package Manager가 나머지 패키지 빌드와 링크 될 수있는 C 라이브러리를 컴파일 할 수 있다고 생각되나  그때까지는 이것이 우리가 할 수 있는 최선의 방법입니다.

Tide가 설치되면 우리는 Swiftychat 앱에서 swiftysockets 을 활용할 수 있습니다.

Start Coding!

main.swift 파일은 매우 간단합니다. ChatterServer를 생성하고 시작하십시오.

main.swift

간략한 main.swift는 우리의 구현이 ChatterServer 클래스에 구현되어 있다는 것을 의미합니다.

ChatterServer.swift:


1. Initialization

 IP와 TCPServerSocket 클래스 (swiftysockets)가 모두 오류를 던질 수 있으므로 nil이 가능한 반환 값임을 알리는 이니셜 라이저. IP는 IP 주소와 포트 정보를 멋지게 캡슐화하고 TCPServerSocket 초기화 프로그램에 인스턴스를 제공합니다. initsucceeds가되면 우리는 주어진 포트에 들어오는 연결을 받아 들일 준비가 된 TCP 소켓을 갖게됩니다.

2. The Main Loop

함수의 이름을 startListening, start, main으로 지정하십시오. 새 클라이언트 연결 (server! .accept ())을 받아들이고 연결된 클라이언트 목록에 추가하는 기본 이벤트 루프입니다. server! .accept ()는  새로운 연결을 기다리고 받아드리는 기능입니다. 꽤 표준적인 것들이죠.

3. Client Management

나머지 ChatterServer에는 모든 "클라이언트 관리"기능이 포함되어 있습니다. 클라이언트를 관리하는 몇 가지 변수와 세 가지 루틴이 있습니다.

우리의 변수는 간단합니다.

  • 연결되어진 클라이언트의 배열 ([TCPClientSocket])
  • 클라이언트를 구분하는데 사용되는 연결 카운트

함수내용은 이렇습니다: 

  • addClient는 TCPClientSocket을 사용하여 연결 수를 증가시키고 클라이언트의 연결에 따라 "관리"되는 NSThread를 설정합니다. 추가 연결이 새로 추가됨에 따라 NSThread가 생성됩니다. 잠시 후에 NSThreadroutine에 대해 이야기하겠습니다. 스레드가 시작되면 addClient는 연결된 클라이언트 배열 끝에 TCPClientSocket을 추가합니다.
  • removeClient는 지정된 클라이언트를 "필터 아웃"하기 위해 필터 함수를 사용하여 연결된 클라이언트 목록에서 클라이언트를 제거합니다. 여기에! == identity 연산자를 사용합니다.
  • broadcastMessage는 ChatterServer를 채팅 서버로 만드는 것입니다. where 키워드를 사용하여 클라이언트가 만든 메시지를 다른 모든 연결된 클라이언트에 브로드 캐스팅하는 필터링 된 배열을 만듭니다. 다시, 우리는! == 연산자를 사용합니다.

스레드는 주 프로세스 내에서 실행되는 별도의 실행 경로임을 상기하십시오. 우리 서버는 연결된 각 클라이언트에 대해 별도의 스레드를 생성합니다. 이제는 그것이 좋은 아이디어인지 아닌지에 대해서는 상황에 따라 달라집니다만 수만 명의 클라이언트를 처리 할 서버를 설계한다면,  말리고 싶습니다.

우리 쓰레드를 한번더 봅시다.

클라이언트 처리 스레드는 또한 TCPClientSocket 클래스의 receiveString 메서드를 통해 입력을 기다리는 루프에 위치합니다. 문자열이 수신되면 서버는 이를 콘솔에 기록한 다음 응답을 브로드 캐스트합니다. try 시도로 인해 연결이 끊어지면 서버는 클라이언트를 제거합니다.

Putting it All Together

우리의 목표는 가능한 한 많이 Swift Package Manager를 사용하여 응용 프로그램을 빌드하는 것입니다. swiftpm에 대한 소개는 자습서를 확인하십시오.

Package.swift에 다음을 추가하십시오.

Sources라는 디렉토리에 main.swift 및 ChatterServer.swift 코드를 추가하십시오.

swifty빌드를 실행하면 두 가지 종속성 (Tide 및 swiftysockets)을 다운로드하여 빌드하고 응용 프로그램 코드를 컴파일해야합니다. 모두 잘되면 .build / debug / 디렉토리에 chatterserver라는 이름의 바이너리가 생깁니다.

Testing it Out

다음 튜토리얼은 멋진 chat 클라이언트를 작성하는 것이지만 지금은 nc (netcat) 명령으로 서버를 테스트 할 수 있습니다. 서버를 시작한 다음 다른 터미널 창에서 nc localhost 5555를 입력하십시오. 연결된 서버 1의 클라이언트 1 창이 표시됩니다. netcat "클라이언트"창에서 CTRL-C를 누르면 서버는 그 이유와 함께 연결 해제 메시지를 인쇄합니다 (예 : 연결 재설정 (연결 재설정)).

실제 테스트를 위해 서버와 연결된 세 개의 클라이언트를 시작합니다.

Chatville
Chatville

왼쪽 터미널에서 채팅 서버가 실행 중입니다. 오른쪽에는 3 개의 클라이언트가 있으며, 각각은 nc localhost 5555 명령을 입력하여 시작됩니다. 각 클라이언트가 연결되면 서버는 연결 메시지를 인쇄합니다.

우리의 broadcastMessage 함수는 브로드 캐스트로부터 메시지의 송신자를 제외시킵니다. 이렇게하면 클라이언트가 자신의 메시지를 다시받지 못하게 되겠지요. 

What’s Next

nc를 클라이언트로 사용하는 것은 약간 지루합니다. 닉네임을 설정할 수없고, 메시지에 "구조"가없고, 타임 스탬프가 없습니다. 위의 예에서 메시지를받는 사람은 누가 작성했는지 전혀 알지 못합니다! swiftysockets에는 이미 TCPClientSocket 클래스가 있으므로 더 강력한 채팅 클라이언트를 만들수 있습니다.

Getting the Code

 here 에 우리의 작은 채팅 서버에 대한 코드를 넣었습니다. 또한 현재 구현되지 않은 채터 클라이언트 프로젝트도 포함되어 있습니다. 다운로드를 하고 최상위 디렉토리에 make를 입력하면 클라이언트와 서버가 모두 빌드됩니다. 주의 사항 : swiftysockets을 사용하기 전에 libtide.a와 관련 헤더를 설치해야합니다!

Comments