TCP/IP 네트워크 프로그래밍 공부를 하면서 나름 정리한 개념인데

만들어보면서도 알 것 같으면서도 어려운 개념인것 같다. 저기 어디에 메모 짱박아두다가 이제 정리 해 본다.


많은 사람들이 블록킹과 동기식을, 논블로킹과 비동기를 같은 용어로 생각하는데 엄연히 다른용어다.


우선 bloking I/O(블록킹), Non-blocking I/O(논블록킹)는 소켓의 동작방식을 나타내는 말이고,

그리고 Syncronous(동기), Asyncronous(비동기)는 서비스나 함수의 동작방식을 나타내는 말이다.



● Blocking I/O


블로킹 입출력 방식은 요청한 작업이 완료되지 않으면 응답을 돌려주지 않는다.

버퍼가 비어있을 경우, 입력이 들어올 때 까지 대기하며 그 동안 다른작업을 할 수 없다.

그러므로 자원의 낭비가 발생하게 된다.


blocking i/o와 달리 nio방식은 다수의 클라이언트의 요청을 처리할 수 있는데,

blocking i/o 에서는 스레드를 사용하여 해결할 수 있다.


하지만 과도한 요청수 만큼 발생한 스레드(멀티쓰레드)는 OOM(Out Of Memory)를 발생 시킬 수 있다.

이를 방지하고자 스레드를 사용하고 반납하는 형식으로 스레드의 개수를 제한하는 스레드풀을 사용한다.


스레드풀의 크기를 정하는 것에는 두가지 관점에서 생각할 필요가 있다고 한다.


첫 번째는 스레드의 개수는 힙에 할당된 메모리의 크기에 의존하는데

클 수록 관리해야 할 스레드 개수가 늘어나므로 가비지 컬렉션의 수행속도가 감소한다.


두 번째는 많은 스레드가 Context Switching(CPU를 점유하기 위한 상태변경)을 하면서

엄청난 오버헤드를 발생시킨다. 이는 cpu 성능저하의 원인이 된다. 


쓰지 말라는 것이 아니고 용도에 맞게 적절하게 사용하는 것이 맞다.

하지만 멀티스레드를 사용하는 병렬처리는 공유자원에 대한 dead lock의 위험 때문에 프로그래밍 하는것이 쉽지 않다.



● Non-Blocking I/O (NIO)


논블로킹은 셀렉터(selector)나 폴(poll)에 여러 소켓을 바인딩 시킨 후

하나의 채널(싱글스레드)에서 관리하는 방식이다. 멀티플렉서에 비유한 것을 본 것 같기도하다.


셀렉터는 주기적으로 채널에 데이터가 들어왔는지 확인하는데

버퍼가 비어있을 경우 즉각 return 시키고 다음 요청을 받을 수 있기 때문에

멀티스레드에 비해 오버헤드가 적다.




● Syncronous (동기)


"동기" 라는 용어는 기본적으로 둘 사이의 싱크를 맞춘다는 말이다.

행위나 목적이 같은것을 시작과 끝을 맞추어 동시에 이루어 지는 방식이다.


● Asyncronous (비동기)


비동기는 요청이 들어와도 꿋꿋이 내가 하던 일을 한다. 들어온 요청은 맡겨버리고 "그 일 다끝나면 알려줘~" 하는 것이다.

그러므로 비동기는 수행되는 순서 및 시작과 끝을 알 수 없다.

동작방식은 메인스레드에서는 내가 하던일을 함과 동시에 요청받은 작업이 별도의 스레드에서 진행되는 거다.

작업이 끝나면 "다 끝났어 가져가" 하며 콜백으로 알려준다. 이러한 방식에는 델리게이트, 퓨처, 프로미스, 콜백 등이 있다. 



동기와 비동기의 간단한 예제를 살펴보자.


1. 싱글스레드 + 동기식


스레드에서 순서대로 요청받은 작업을 처리한다.

하지만 앞의 작업이 모두 끝날 때 까지 뒤의 작업은 무한대기다.



2. 멀티스레드 + 동기식


각각의 스레드에서 요청을 1:1로 맡아 작업을 처리한다.



3. 싱글스레드 + 비동기식


일단 모든 요청을 결과에 상관없이 반환한다.

그리고 작업이 끝남과 동시에 결과를 알려준다.



4. 멀티스레드 + 비동기식


모든 요청을 여러 스레드가 나누어 결과에 상관없이 반환한다.

그리고 작업이 끝남과 동시에 결과를 알려준다.

가장 빠른 속도가 예상되며 2번과 3번을 섞은 느낌이다.




아래는 동기와 비동기 방식의 간단한 예제다 (출처 : http://malchooni.name/)


동기방식은 A노드와 B노드사이의 작업 처리 단위(transaction)를 동시에 맞추겠다는 뜻이다.
얄순이에게 보내는 말춘이의 오천원‘ 예를 보자.

ex1

  1. 말춘계좌는 오천원을 뺄 생각을 하고 있다.
  2. 말춘계좌는 얄순계좌에게 오천원을 전송한다.
  3. 얄순계좌는 오천원이 수신되었단 걸 인지 하고 말춘계좌에게 ‘받았음’을 전송한다.
  4. 이로써 말춘계좌는 -5000원을 하고 얄순계좌는 +5000원을 한다.

이 예제에서 눈여겨 볼 부분은 마지막이다. 말춘계좌와 얄순계좌는 서로의 요청과 응답을 확인한 후 같은 일을 동시에 진행했다.
‘계좌이체’라는 작업단위는 위의 그림처럼 동기화를 해야한다. 그래야지 한쪽이 보냈는데 못받았거나, 안보냈는데 받은 상황이 없을 것이다.

비동기방식은 이와 반대로 노드사이의 작업 처리 단위를 동시에 맞추지 않아도 된다는 것이다.
말춘학생의 시험지는 얄순선생이 채점한다‘ 예를 보자.

ex2

  1. 말춘학생은 시험지를 열심히 푼다.
  2. 시험지에 답안 작성을 완료한 말춘학생은 시험지를 얄순선생에게 전송한다.
  3. 얄순선생은 말춘학생의 시험지를 채점한다.
  4. 채점이 다 된 말춘학생의 시험지를 다시 전송한다.
  5. 말춘학생은 얄순선생이 채점한 시험지를 받아 본다.

말춘학생과 얄순선생은 시험지라는 연결고리가 있지만 시험지에 행하는 행위(목적?)은 서로 다르다. 한사람은 시험지를 푸는 역할을 또 한 사람은 그 시험지를 채점하는 역할을 한 것이다. 그래서 둘의 작업 처리 시각을 따지자면 일치하지 않는다. 일치하지 않아도 된다.

여기서 블록과 논블록의 차이를 간략히 설명해 보겠다. 말춘학생이 시험지를 얄순선생에게 건낸 후 얄순선생의 얼굴만 바라보며 채점 된 시험지를 받기 기다린다면 말춘학생은 블록 상태인 것이다. 하지만 말춘학생이 시험지를 건낸 후 채점이 완료 됐다는 이벤트를 받기 전까지 춤을 춘다거나 클래시오브클랜을 한다던가 다른 일을 하게 된다면 말춘학생의 상태는 논블록 상태인 것이다.
동기와 비동기, 블록과 논블록은 헷갈리기 쉬운 개념이다.

자바네트워크 프로그래밍 블록과 논블록 *

마지막으로 정리를 하자면 동기와 비동기는 어떤 작업 혹은 그와 연관된 작업을 처리하고자 하는 시각의 차이이다. 동기는 추구하는 같은 행위(목적)가 동시에 이루어지며, 비동기는 추구하는 행위(목적)가 다를 수도, 동시에 이루어지지도 않는다. 


'전공과목 > Network' 카테고리의 다른 글

OSI 7 Layer [OSI 7 계층]  (0) 2016.10.18
[네트워크] 빅엔디안 리틀엔디안  (1) 2016.10.12

■ OSI 7 계층이란


 ISO에서 서로 다른 시스템 간의 통신을 허용하기 위해 OSI 참조모델을 만듬

● OSI 참조모델은 호환성이 있는 네트워크 프로토콜의 개발을 위한 지침 제공

● OSI 참조모델은 네트워크가 제공하는 여러가지 기능을 7개의 계층으로 나누어 식별

● 각 계층은 독특한 기능을 가지며, 전체 모델이 올바르게 작동할 수 있도록 계층 간에 상호 의존





■ 물리 계층


 역할

 ● 시스템간의 물리적인 연결, 혹은 전기 신호의 복원 서비스를 제공한다.

     (데이터 ㅡ> 전자신호로, 전자신호를 ㅡ> 데이터로 변환)

 통신단위

 Bit

 장비

 리피터(물리적 신호를 증폭하여 신호가 감쇠되는것을 방지), 허브




■ 데이터링크 계층


 역할 

 ● 물리적으로 연결되어 있는 호스트끼리 통신을 담당한다.

    (MAC 주소를 연결, 물리적 장치들간의 연결을 담당 ㅡ> 물리회선을 통신채널로 변화)

 ● 흐름제어 : 보내는 측과 받는 측 사이의 속도차를 제어한다.

 ● 에러제어 : 전송오류를 검출하고 수정한다.

 ● 순서제어 : 패킷이나 ACK 신호를 혼동하는 것을 피하기 위해, Sequence Number를 부여.

 통신단위 

 Frame

 프로토콜

 MAC(이더넷, 토큰링), PPP

 주소체계

 MAC

 장비

 스위치,  브릿지(두개의 LAN을 연결해주는 통신망 연결 장치)




■ 네트워크 계층


역할

 ● 헤더에  논리적 주소를 추가

 ● 경로제어(라우팅) : 송신에서부터 수신까지의 패킷의 경로를 제어한다.

통신단위 

 Packet

프로토콜 

 IP(V4/V6), ARP(브로드캐스트 방식으로 IP를 이용하여 MAC주소를 알아냄), RARP(ARP의 반대)

주소체계 

 IP

장비 

 라우터  (LAN:LAN 또는 LAN:WAN을 연결하는 네트워킹 장치)


※ ARP 프로토콜의 사용 예


A컴퓨터가 192.168.0.123 주소로 패킷을 보내려고 할 때, IP주소(논리적:변경가능)는 알고 있지만 MAC주소(물리적:고유)는 모르는 상태다.

그럼 A는 브로드캐스팅(ARP프로토콜)을 통해 192.1368.0.123 누가쓰냐? 라고 물어본다.

B는 어 그거 내가 쓰는데? 라고 응답하게 됩니다. B이외에 C,D...등등은 해당되지 않기 때문에 응답을 하지 않는다.

그럼 A는 B에게 MAC주소좀 알려줘 하게 되고, B의 MAC주소를 받게되고 패킷을 보낼 수 있다.

그 후에는 A는 B의 MAC주소를 ARP 테이블에 추가했기 때문에 (IP와 MAC을 mapping 시켜놓은 table), 패킷을 바로 보낼 수 있다.




■ 전송 계층


역할

 ● 헤더에 포트번호를 추가

 ● 어떤 종류의 네트워크가 사용되었는지를 사용자가 의식하지 않도록 논리적 통신을 지원.

 ● 프로세스와 프로세스(종단간, End-To-End)의 통신을 담당한다.

 ● 데이터가 중복, 유실된 것을 발신자에게 재전송을 요구해 신뢰적인 전송을 보장한다.

통신단위 

 Segment

프로토콜 

 TCP, UDP

주소체계 

 Port

장비 

 게이트웨이




■ 세션 계층


 역할

 ● 응용 프로그램간의 연결과 ,유지와, 연결을 끊는 역할을 담당한다.

 통신단위

 Data




■ 표현 계층


 역할

 ● 서로 다른 데이터 표현방식을 하나의 통일된 형식으로 변환하는 역할

 ● 암호화(Encryption), 압축(Compression), 코드변환(ASCII, Binary, BCDIC)

 통신단위

 Data

 프로토콜

 JPG, MPEG




■ 응용 계층


 역할

 ● 사용자 계층을 말하며, 사용자 인터페이스를 제공한다.

 통신단위

 Data

 프로토콜

 DHCP(동적할당), DNS(도메인), FTP(파일전송), HTTP(웹), POP3(이메일), RIP,

 SMTP(이메일), SSH(원격), TELNET(원격), XMPP




■ 출처


http://mintnlatte.tistory.com

https://ko.wikipedia.org/

http://hahahoho5915.tistory.com/12


빅 엔디안과 리틀 엔디안은 컴퓨터 메모리에 저장된 바이트들의 순서를 설명하는 용어이다.
컴퓨터에서는 어떤 크기의 데이터를 메모리에 저장할 때 바이트 단위로 나누어 저장하는데,
이러한 방식을 바이트 오더(Byte Order)라고 한다.


[그림] 레지스터와 메모리 위치 매핑관계, 출처 : 위키피디아(www.wikipedia.org)




리틀-엔디안 (Little-Endian)

낮은(시작) 주소에 하위 바이트부터 기록, Intel CPU 계열
예) 32비트형 (4바이트) 값: 0x01020304

하위 주소0x040x030x020x01상위 주소


빅-엔디안 (Big-Endian)

낮은(시작) 주소에 상위 바이트부터 기록, Sparc / RISC CPU 계열
예) 32비트형 (4바이트) 값: 0x01020304

하위 주소0x010x020x030x04상위 주소


※ 0x는 16진수를 나타내는데, 16진수는 각 자리당 0~F(16개)로 표현한다.

각 자리당 16개를 나타낼 수 있으므로 4비트가 필요하다. (2^4=16)

따라서 1byte는 8bit니까 바이트씩 끊어 저장하면 2개씩 저장된다.





리틀-엔디안 (Little-Endian)을 사용하는 이유


빅엔디안은 우리 눈으로 보기 쉽지만,  ALU(산술연산유닛)에서 메모리를 읽는 방식이

메모리 주소가 낮은 쪽 ㅡ> 높은 쪽으로 읽기 때문에 리틀엔디안을 사용하면 산술연산 수행이 더 쉽다.




■ 리틀-엔디안, 빅-엔디안을 맞춰주어야 하는 이유 


네트워크 프로그래밍에서 데이터를 다른 시스템으로 전송할 때

서로 다른 데이터 저장 방식의 시스템 끼리 통신하게 되면 전혀 엉뚱한 값을 주고 받을 수 있기 때문이다.


소켓은 기본적으로 빅엔디안으로 통일되어 있다.



■ 예제



#include <stdio.h>

int main()
{
        int inum = 0x12345678;     ㅡ> 16진수 12345678 저장

        unsigned char *p;          ㅡ> 포인터변수 생성

        p = (unsigned char*)&inum; ㅡ> 변수 inum 의 주소를 p 에 저장


        printf("%08X\n",inum);     ㅡ> inum의 값 12345678 출력

        printf("%p\n",&inum);      ㅡ> inum의 주소 0xbfd256ec 출력



        printf("%p\n",p);          ㅡ> p에 저장된 값(inum의 주소) 0xbfd256ec 출력

        printf("%02X\n",*p);       ㅡ> p에 저장된 값(주소)가 가르키는 값 처음 2자리 78 출력



        ++p;                       ㅡ> p에 저장된 값 (inum의 주소) 증가

        printf("%p\n",p);          ㅡ> 0xbfd256ed

        printf("%02X\n",*p);       ㅡ> 56



        ++p;

        printf("%p\n",p);          ㅡ> 0xbfd256ee

        printf("%02X\n",*p);       ㅡ> 34



        ++p;

        printf("%p\n",p);          ㅡ> 0xbfd256ef

        printf("%02X\n",*p);       ㅡ> 12



        return 0;

} 



예제를 통해 역순으로 출력되는 것을 보아 리틀-엔디안이다.




■ 후기


틀린 것 있으면 수정좀 부탁드립니다.



■ 출처


https://firejune.com

http://forum.falinux.com/

http://andrew0409.tistory.com/105

'전공과목 > Network' 카테고리의 다른 글

동기와 비동기 & 블록킹과 논블록킹 정리  (0) 2016.11.26
OSI 7 Layer [OSI 7 계층]  (0) 2016.10.18

+ Recent posts