본문 바로가기

iOS/iOS

iOS) Socket 통신 (1) Socket 기초, TCP, UDP

안녕하세요. 소들입니다 :D

 

이번에 공부할 내용은 바로바로..

Socket 통신입니다!!!!!

 

Socket 통신하면 왠지 어려워 보이지 않나요? TT..

저는 HTTP 통신만 하다가 처음 Socket 통신을 딱 마주했을 때 되게 막막했던 것 같아요.
물론 지금도 Socket 통신 이론을 얘기해보자 하면 어려워요 :D


하지만!!!!!!!!!! 다행히!!!!!!!!!!! iOS에서의 Socket 통신 구현은 그렇게 어렵지 않습니당.
기존 C언어로 Echo Server & Client를 구현하려 하면 꽤 까다로운 작업이 많거든요?
근데 그런 작업을 굳이 다 해주지 않아도,

NSStream 이놈을 사용하면 정말 간단하게 소켓 통신을 할 수 있답니다 ヾ(*´∀`*)ノ 

그래도 기존 소켓 통신이 어케 구동되는진 대충 보고 갈 거에여

 


자 그럼 들어가기 전에,
Socket 통신에 대해 먼저 알아보고 갈게요.
궁극적으론 이 Socket에 TLS 적용하는 방법까지 알아볼 것입니다 :) 출발~

 

 

 

 

1. 소켓(Socket)이란?

 

자 그럼 먼저 소켓이 뭔지부터 알고 갑시다.
굳이 어려운 말로 정의하자면

정규 유닉스 파일 기술자를 이용하여 다른 프로그램과 정보를 교환하는 방법

ㅋㅋㅋㅋ 뭐라는거야ㅠㅠ
먼저, 유닉스가 무엇이냐면, 그냥 운영체제의 하나라고 생각하면 돼요.
이 유닉스에선 모~든 것이 파일로 되어 있어요.

소켓도 유닉스에선 '파일'로 취급해요.
그리고 이 유닉스의 프로그램들은 모든 입출력(read, write)을 할 때   파일 기술자(File Descriptor) 라는 것을 통해서 해요.

디스크립터 라는 것이 더 익숙할지 모르지만, 여기선 그냥 '기술자' 라고 표현하겠습니다.

여기서 파일 기술자라는 것은,
열려진 파일을 의미하는 정수(인덱스) 번호예요.

 소켓 기술자(Socket Descriptor) 라는 것은 소켓을 만들고 얻은 파일 기술자를 말해요.

 

와 어렵다~! 뭔말이야~~!
쉽게말해 내가 서버랑 소켓 통신을 하고 싶어요.

그러면 소켓을 생성해야겠죠? socket()이라는 함수를 통해 생성할 수 있어요.

socket()이라는 함수를 호출하면, 내부적으로 소켓에 사용할 파일을 하나 열어요.

그리고 그 파일의 index 번호를 return 해줘요.

이때 이 index 번호가 소켓 기술자라는 것이고,

이제 이 소켓 기술자에 대고 send(), recv()를 하며 통신을 하는 거예요.
만약 소켓을 무한대로 생성해서 더 이상 파일을 열지 못한다면, 소켓 생성 에러가 날 거예요.

소켓 기술자는 열려진 파일의 index이기 때문에, 정수형으로 되어 있어요.
내가 만약 A라는 소켓을 만들고 그 소켓 기술자가 3이라면,
B라는 소켓을 만들면 그 소켓 기술자는 4이고
뭐.. 이런 식으로 생각하시면 됩니다 :D

(파일 기술자의 0,1,2는 이미 할당되어 있어서 3부터 쓸 수 있습니다)

C언어 같이 정말 low 레벨에서 구현하자면 위와 같이 이 소켓 기술자를 직접 이용해서 구현을 해요.

다음 사진과 같이요

 

 

 

소켓 기술자인 sock_fd는 정수형 자료형이기 때문에,

리틀앤디안, 빅앤디안을 신경써서 바꿔주는 작업(htons 등)도 해야해요.

간단히 주소와 포트 번호를 설정하더라도 다음과 같이 말이졍.

 

 

 

뭐 이 뒤로도 connect()를 호출하고 성공 시 send()/recv(), 끝낼 시 close() 등을 호출 하는게

일반적인 socket client 통신이에요.

(서버라면 bind(), listen(), accept() 작업들이 추가되겠죠)

더 나아가 읽을 데이터가 있을 때까지 blocking(블로킹) 되지 않게 더 심화된 작업들도 추가해줘야 돼요 T.T

여기선 간단한 소켓 구동 방식과 iOS가 얼마나 간편히 소켓 통신을 할 수 있는지를 설명하기 위함이니
더 깊게 하지 않고 이정도만 하고 넘어갈게요 (휴)

 

그렇다면 iOS에서도 소켓 통신을 위해 이렇게 많고 귀찮고 어려운 작업들을 다 해줘야 할까요? (본론)

물론 한다면 하죠! 하지만! 우리가 사용하는 언어는! 좀더! high 레벨의 언어잖아요?
소켓 기술자고 뭐시기고 모든 건 다 프레임워크화 되어 있고,
우린 그냥 상위레벨에서 제공하는 메서드를 갖다 쓰면 정말 쉽게 할 수 있습니다.

위에서 말한 내용 다 몰라도 IP, Port만 알면 통신이 가능함..ㅎㅎ 세상 편함

 

그렇다면 왜 위에 내용을 헷갈리게 왜 적었냐면 할 말은 없는데..

아무리 모든게 고도의 프레임워크화 되어 있다고 해도..

적어도 그 안에서 어떻게 동작하는지는 조금이라도 알아보자는 취지에서..?:)

프레임워크화 되어 있어 우리가 못볼 뿐, 그 안에선 모두 위와 같은 작업들을 열심히! 알아서! 해주고 있을 거랍니다.

 

쩄든!! 소켓통신은 소켓 기술자라는 것을 이용해 send, recv를 하는 통신이구나! 
정도만 이해 합시다 :D

이제 소켓에서 데이터를 보내기 위해 사용하는 프로토콜을 알아볼 것인데, 가장 대표적으로 두 가지 종류가 있어요.

 1. TCP  

 2. UDP 

위 두가지만 있는 것은 아니지만, 위 두가지만 알아도 됩니다.
많이 들어보셨죠? 그럼 이 둘의 차이점에 대해서도 명확히 설명하실 수 있나요? :D

 

 



2. TCP vs UDP

TCP와 UDP의 차이점에 대해 알아봅시다 :)

 

 

 

 (1) TCP (스트림 소켓) 

 

TCP는 데이터를 메세지 형태로 보내기 위해 IP와 함께 사용하는 프로토콜입니다.

IP가 데이터 배달을 처리한다면, TCP는 패킷을  추적 관리 합니다.

여기서, 패킷을 추적 관리한다는 것은 무엇일까요?

 

먼저, 패킷이라는 것은 하나의 온전한 데이터 뭉텅이가 아닙니다.

데이터를 보낼 땐 한번에 몽땅 보내는 것이 아닌, 효율성을 위해 조각 조각 내서 나누어서 보내요.

여기서 이 조각 조각으로 나눠진 데이터를  패킷 이라 한답니다.

이제 목적지에선 이 나눠진 데이터를 온전히 받아야겠죠?

 

이처럼 데이터가 온전히 갔는지 확인하기 위하여 TCP는 패킷에 번호를 부여해서 패킷이 중간에 손실되진 않았는지 확인을 하고, 목적지에선 나누어진 패킷이 다시 온전한 데이터가 될 수 있도록 재조립을 해용.

이 과정이 바로 패킷을  추적 관리 한다는 것입니다 :D

 

*IP, Port : IP 주소로 Socket이 연결되면 해당 컴퓨터들끼리 연결이 되는 것입니다. Port란, 해당 컴퓨터 안에서 어떤 프로세스에 연결할 것인가 입니다.(컴퓨터 안에 어려 프로세스들이 실행 중일 수 있으니) 아파트 주소가 IP라면, Port는 호수입니다. 

 

 

TCP 소켓의 특징은 다음과 같습니다.

 

 

⦁ 연결형 서비스로 안정성, 신뢰성을 보장한다.

⦁ 발신자와 수신자를 연결하여 논리적 경로(가상 회선 방식)을 배정한다.

⦁ 3-Way Handshake 방식을 통해 연결을 맺고, 4-Way Handshake를 통해 해제한다.

⦁ 서버가 응답을 주지 않으면 계속적으로 요청하게 된다. (어느 시점에 포기할 수도 있음)

⦁ 서로 데이터를 주고받을 수 있는 양방향 통신이며, 일대일 통신(unicast)이다.

⦁ 패킷의 순서는 정확히 유지되고, 에러도 교정된다.

⦁ 데이터 흐름 제어 및 혼잡 제어가 가능하다.

⦁ UDP 보다 속도가 느리다.

 

 

3-Way Handshake는,

목적지와 수신지를 정확히 하여 정확한 전송을 보장하기 위해 하는 것입니다.

 

그렇다면, 어떻게 안전성과 신뢰성을 보장할 수 있을까요?

바로 Ack, 재전송으로 안정성을 제공받아요.

 

 

 

TCP는 패킷을 받을 때마다 Ack라는 별도의 패킷을 만들어서 보내요.

여기서  Ack 라는 것은 Acknowledge의 약자로, "잘 받았음" 이라는 뜻으로 사용해요.

송신자가 패킷을 보내면, 수신자는

"n번 패킷 잘 받았습니다. 이제 n+1번 패킷 주세요"

라고 Ack를 보내면서 데이터가 잘 오가고 있음을 체크하는 것입니다.

 

  재전송 이라는 것은, Ack가 오지 않았을 때 송신자가 패킷을 다시 보내버리는 작업이에요.

Ack가 오지 않는 경우는 다음 두 가지 경우예요.

- 수신자가 패킷을 받지 못해 정말 Ack를 보내지 못한 것

- 수신자는 패킷을 잘 받아서 Ack를 보냈으나, Ack가 중간에 유실되어 버린 것

둘 중에 어떤 경우 때문에 Ack가 안온진 모르지만, 송신자는 일정 시간 동안 Ack가 오지 않으면 패킷을 재전송 합니다.

비효율적일진 몰라도, 데이터를 못받거나 하는 일은 절대 없으니 확실히 안정적이겠죠? :)

 

 

 가상 회선 방식 을 제공한다는 것은,

 

 

 

 

 

이런식으로 패킷 1,2,3이 사이좋게 정해진 길(파란색 선)으로만 가죠?

이 길이 가상 회선(논리적 경로)가 되는 것입니다.

TCP에선 이 가상 회선을 배정해주기 때문에, 패킷들은 이 회선을 따라 움직입니다.

따라서 패킷의 순서가 뒤바뀔일 없이 순차적으로 도착합니다 :)

 

또한, 데이터 흐름 제어 나  혼잡 제어  같은 기능도 가능해요.

 흐름제어 는, 데이터를 송수신 하는 곳과 수신하는 곳의 데이터 처리 속도를 조절하여,

수신자의 버퍼 오버플로우를 방지합니다. (송신자가 미친듯이 데이터를 쏴버리면 수신자가 문제가 생길 수 있으니 그것을 조절해줌)

 혼잡 제어 는, 네트워크 내의 패킷 수가 넘치지 않게 방지하는 것입니다.

패킷의 수가 너무 많아지면 패킷을 조금만 전송하여 네트워크 혼잡을 막는 것입니다.

 

뭔가 기능이 많아보이죠? 

기능이 많으면 물론 좋지만, 그만큼 CPU의 부담도 커진다는 얘기예요.

때문에, 속도가 느려지는 것입니다.

저런 작업들을 해주는 것이 속도 면에서 영향을 끼치니까요 :D

그럼 UDP는 저런 작업을 안해주니까 속도가 빠른 거겠죠?!?

 

따라서 TCP는 연속적으로 데이터를 주고받을 때 보단,

신뢰성 있는 연결을 중시할 때 사용합니다.

 

연속적으로 데이터를 주고받는단 것의 대표가 영상같은 실시간 Streaming 일 때예요.

영상 스트리밍 같은 경우 1초에만 해도 엄청나게 많은 프레임 패킷을 연속적으로 받아요.

그럴 때 만약 프레임 패킷 하나가 손실 되었다고 해서

다시 손실된 데이터를 요청하고 한다면... 실시간이라는 것에 조금 치명적일 수 있겠죠.(요청할 동안 버벅일테니..)

사실 프레임 패킷하나가 손실되었다 해서 재요청하는 것보단, 그냥 무시하고 계속 재생되는 게 더 맞을테니까요. 

 

 

 

 

 (2) UDP (데이터그램 소켓) 

 

UDP에선 데이터를  데이터그램 단위로  처리합니다.

데이터그램이란 독립적인 단계를 지니는 패킷입니다.

UDP도 데이터그램을 받기 위해선 TCP와 같이 IP를 사용합니다.

다만, 소켓을 만들어 서로 연결을 맺는 구조가 아닌, 소켓을 만들어 그냥 UDP 서버 IP, Port로 데이터를 보내는 개념입니다.

그러면 UDP 서버도 Client IP, Port로 그냥 데이터를 보내 버리는 것입니다.

그렇기 때문에 UDP 서버 하나에 여러 Client들이 붙어서 데이터를 받을 수 있습니다.

 

보통 TCP는 전화에, UDP는 편지에 많이 비교합니다.

TCP는 상대방의 번호(IP, Port)로 전화를 걸고 연결이 되면, 서로 의사소통을 주고 받을 수 있죠.

"너 내가 방금 한 말 들었어?"

"아니 못들었어! 다시 해줘!"

이런 식으로  :D

 

그러나 UDP는 편지이기 때문에, 상대방의 집주소(IP, Port)만 알면 그냥 편지에 데이터 쓰고 우체통에 넣어버리는 것입니다.

수신자는 자신의 편지통에 편지가 왔는지 직접 확인할 때까진 편지가 온지 모를테고,

또 송신자 역시 편지를 보내긴 했지만 수신자가 실제 그 편지를 받았는지, 읽었는지, 중간에 날라갔는지엔 관심 없습니다. 

 

 또한 UDP는 TCP와 달리 비연결형 소켓이기 때문에, 연결을 위해 할당되는 논리적 경로가 없습니다.

 

 

 

 

 

 

TCP와 달리 파란 선(가상 회선)이 없죠?

그렇기 때문에 UDP는 데이터들이 서로 다른 경로로 전송됩니다.

1,2,3번 패킷이 서로 독립접인 관계고, 실제로 보낸 순서대로 도착하지 않을 수도 있습니다.

이런 패킷들을 데이터그램이라 하고, 이러한 방식을 UDP라 합니다.

UDP 소켓의 특징은 다음과 같습니다.

 

 

⦁ 비연결형 서비스로 데이터그램 방식을 제공한다.

⦁ 정보를 주고받을 때, Handshake와 같은 신호 절차를 거치지 않는다.

⦁ UDP Hedaer의 CheckSum을 통해 최소한의 에러만 검출한다.

⦁ 일대일 통신(unicast), 일대다 통신(broadcast), 다대다 통신(multicast)

⦁ 데이터가 제대로 도착할 수도, 중간에 유실될 수도, 순서가 바뀌어 도착할 수도 있다.

⦁ TCP보다 속도가 빠르다.

⦁ 신뢰성이 낮다.

 

 

UDP의 경우 연결을 맺고 끊는 과정이 존재하지 않고, Ack를 보내지도 않으며,

 패킷에 순서를 부여하여 추적 관리하거나, 혼잡, 흐름 제어도 하지 않기 때문에

속도가 빠르고 네트워크 부하도 적습니다.

그러나, 중간에 패킷 손실과 같은 것을 체크할 수 없기 때문에,

데이터 전송 면에서 신뢰성이 떨어집니다.

 

따라서, TCP와 반대로

신뢰성보다 연속성이 중요한 서비스에서 사용 됩니다. (영상 실시간 Streaming 등)

 

 

 


.

.

.

자, 이제 소켓에 대한 이론은 거의 모두 공부한 것 같아요 :D
네트워크에 대해 이해가 있으신 분이면 어렵지 않았을 테고, 
처음 공부한다면 꽤 어려웠을 것 같아요.


이번 포스팅은 이론으로 마치겠습니다!
다음 포스팅에선 NSStream을 이용해, 실제 소켓을 어떻게 만들고 통신하는지 델꼬 올게여
궁금한 점이나, 틀린 점이 있으면 댓글 남겨주세요 

읽어주셔서 감사합니다 :D

 

 

+ iOS 소켓 통신은 추후에 다시 올리겠슴돠..... 바빠져서 죄송함돠

 

 

 

 


이번 포스팅은 

https://mangkyu.tistory.com/15?category=762469

 

[TCP/UDP] TCP와 UDP의 특징과 차이

오늘은 네트워크의 계층들 중 전송 계층에서 사용하는 프로토콜에 대해서 알아보려고 합니다. 전송계층은 송신자와 수신자를 연결하는 통신서비스를 제공하는 계층으로, 쉽게 말해 데이터의 ��

mangkyu.tistory.com

를 참고하여 작성하였습니다 (정리가 정말 잘 되어 있더라구요  +(๑❛ᴗ❛๑)+ )

 



Calendar
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
최근 댓글
Visits
Today
Yesterday