HTTP 3핸드 쉐이킹 캡쳐

통신/TCP_IP 2020. 10. 12. 10:00

스트림 데이터를 받는데,

3핸드쉐이킹 후에 데이터를 주고 받는 것을 캡쳐해 봤다.

HTTP REST API의 GET으로 보낼 때, HEX 값 같은 것이 아닌 문자열을 주고 받는 것을 확인하였다.

위에

'빨강 {' 이 3핸드 쉐이킹이고

'빨강 -' 가 REST API의 GET, 밑에 빨강 박스가 그 내용이다.

 

 

 

 

 

 

 

'통신 > TCP_IP' 카테고리의 다른 글

Ethernet, IP, TCP, UDP Frame  (0) 2014.10.15
TCP/IP 4 계층  (0) 2014.10.15

설정

트랙백

댓글

Blocking / Non-Blocking

통신 2019. 9. 18. 20:23

Blocking

I/O 작업은 유저레벨에서 직접 수행할 수 없다. 실제 I/O를 수행하는것은 커널레벨에서만 가능하다. 따라서 유저 프로세스(또는 쓰레드)는 커널에게 I/O를 요청해야한다. I/O에서 블로킹 형태의 작업은 유저 프로세스가 커널에게 I/O를 요청하는 함수를 호출하고, 커널이 작업을 완료되면 함수가 작업 결과를 반환한다.

 

http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch06lev1sec2.html

I/O 작업이 진행되는동안 유저 프로세스는 자신의 작업을 중단한채 대기해야한다. I/O작업이 CPU자원을 거의 쓰지 않기 때문에 이런 형태의 I/O는 리소스 낭비가 심하다.

만약 여러 클라이언트가 접속하는 서버를 블로킹방식으로 구현한다고 가정해보자. I/O작업이 blocking 방식으로 구현되면 하나의 클라이언트가 I/O작업을 진행하면 해당 프로세스(또는 쓰레드)가 진행하는 작업을 중지하게 된다. 따라서 다른 클라이언트의 작업에 영향을 미치지 않게 하기 위해서 클라이언트 별로 별도의 쓰레드를 만들어 연결시켜주어야 할 것이다. 그러면 쓰레드 수는 접속자 수가 많아질 수록 엄청나게 많아지게 된다. 쓰레드가 많으면 CPU의 컨텍스트 스위칭 횟수가 증가할 것이며, 이때 사용되는 컨텍스트 스위칭 비용 때문에, 실제 작업하는 양에 비하여 훨씬 비효율적으로 동작하게 될 것이다.

 

Non-Blocking

Blocking 방식의 비효율성을 극복하고자 만들어진 것이 Non-Blocking 방식이다. Non-Blocking은 I/O작업을 진행하는 동안 유저 프로세스의 작업을 중단시키지 않는다. 유저 프로세스가 커널에게 I/O를 요청하는 함수를 호출하면, 함수는 I/O를 요청한 다음 진행상황과 상관없이 바로 결과를 반환한다.

 

http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch06lev1sec2.html

 

위 그림은 Non-Blocking 방식으로 구현된 I/O의 대표적인 사례를 잘 보여준다. 유저 프로세스는 recvfrom함수를 호출하여 커널에게 해당 소켓으로부터 데이터를 받아오고 싶다고 요청하고 있다. 커널은 이 요청에 대해서 상대방의 데이터를 전송 받아서 recvBuffer에 저장하고, 유저에게 그 내용을 복사해줘야 한다. 상대방으로 부터 데이터를 받는 중에 recvBuffer가 비어있다면 유저 프로세스가 커널에게 받아올 수 있는 정보는 없다. 따라서 recvfrom 함수는 아직 작업 진행중이란 의미로 "EWOULDBLOCK"을 리턴한다. 이 결과를 받은 유저 프로세스는 다른 작업을 진행할 수 있다. 만약 recvBuffer에 유저가 받을 수 있는 데이터가 있다면, 버퍼로 부터 데이터를 복사하여 받아온다. recvBuffer는 커널이 가지고 있는 메모리에 적재되어 있으므로 메모리간 복사가 일어나 I/O보다 훨씬 빠른 속도로 데이터를 받아올 수 있다. 이때 recvfrom함수는 빠른 속도로 읽을 수 있는 데이터를 복사해주고 복사한 데이터의 길이와 함께 반환한다. 위의 모든 반환이 I/O의 진행시간과는 관계없이 빠르게 동작하기 때문에, 유저 프로세스는 자신의 작업을 오랜시간 중지하지 않고도 I/O 처리를 수행할 수 있다.

 

Socket에서 Non-Blocking 구현

socket 프로그래밍에서 해당 소켓의 I/O Blocking/Non-Blocking 모드를 결정할 수 있다.

 

//ioctlsocket함수: 소켓의 I/O 상태를 변경하는 함수 //리눅스에서는 ioctl함수가 같은 기능을 지원한다. ULONG isNonBlocking = 1; ioctlsocket(socket, //Non-Blocking으로 변경할 소켓 FIONBIO, //변경할 소켓의 입출력 모드 &isNonBlocking //넘기는 인자, 여기서는 nonblocking설정 값 );

 

두 번째 인자에 어떤 값을 넣느야에 따라서 설정 값의 의미가 달라지긴 하지만, Non-Blocking으로 만드는데에는 이 호출만으로 충분하다. 소켓은 초기 설정이 Blocking으로 되어있으므로 Non-Blocking 모드로 진행하기 위해서는 이 함수 호출이 필수적이다.

 

char str[BUF_SIZE] = {0,}; //받을 버퍼 unsigned int strLen = 0; //받고싶은 데이터의 길이 unsigned int length = 0; //지금까지 받은 데이터의 길이 unsigned int recvLen = 0; //이번에 받은 데이터의 길이 ... while(TRUE){ if ( recvLen = recv( sock, str+length, strLen, 0) < 0 ){ //recvfrom 호출하여 결과값을 받는다. 0보다 작으면 받을 수 있는 데이터가 없는것 if ( WSAGetLastError() == WSAEWOULDBLOCK ){ //WOULDBLOCK이라면 대기시킨다. Sleep( 2000 ); /* Sleep for 2 milliseconds */ } else{ printf("No data Error.\n"); break; } } else { length += recvLen; if(length >= strLen) //다받았으면 중지 break; } }

 

while문을 사용하여 Blocking 모델과 다를바 없이 사용하고 있기 때문에 좋은 사용 방법이라고는 생각하지 않지만, 각 부분을 따로 놓고 생각하면 Non-Blocking형식으로 I/O를 구현하는 방식들을 잘 보여주는 예시이다. 논블럭 recv함수는 읽을 수 있는 데이터만 복사해서 가져오고 그 결과를 반환한다. 원하는 사이즈의 데이터를 받으려면 데이터를 축적하여 받아와야할 것이다. 함수가 반환하는 값에 따라서 적절하게 동작하도록 코딩하면 원하는 결과를 얻을 수 있을 것이다.

 

그렇다면 이제 Blocking 식 서버에서는 할 수 없었던 싱글 쓰레드 다중접속 서버를 만들 수 있다. accept된 소켓을 하나씩 클라이언트 세션으로 만들고 클라이언트 매니저가 연결된 클라이언트들을 관리한다. 클라이언트 매니저는 모든 클라이언트 세션들을 계속해서 순회하면서 recv를 호출하여 입력을 받는다. 그리고 받은 내용에 대한 처리를 해서 send로 응답해줄 수 있다. 이때 수행되는 작업이 Non-blocking이므로 따로 쓰레드를 만들지 않아도 충분히 잘 동작할 것이다. 이 구현방식의 문제는 클라이언트가 따로 입력을 하지 않아도 계속해서 recv로 확인을 해줘야한다는 점이다. 버퍼가 준비되었는지를 확인하는데 recv를 쓰는것은 리소스를 남용하는 것이다. recv말고 그냥 해당 소켓의 버퍼를 체크할 수 있는 방법이 있다면, 읽고 쓸 수 있는 상태에 처한 소켓들을 가려낼 수 있다면 더 효과적인 방법으로 서버를 만들 수 있을 것이다.

 

동기 비동기 I/O 통지모델


 

I/O 이벤트 통지 모델

이벤트 통지 모델은 Non-Blocking에서 제기된 문제를 해결하기 위해서 고안되었다. I/O처리를 할 수 있는 소켓(혹은 파일 디스크립터)을 가려내서 가르쳐준다면, 다시말해 입력 버퍼에 데이터가 수신되어서 데이터의 수신이 필요하거나, 출력버퍼가 비어서 데이터의 전송이 가능한 상황을 알려준다면, 위에서 이야기한 구조보다 더 단순하고 효과적으로 다중 I/O모델을 처리할 수 있을 것이다. I/O 이벤트를 통지하는 방법은 크게 동기형 통지모델과 비동기형 통지모델로 나눌 수 있다. 

 

동기형 통지모델

동기(synchronous)와 비동기(asynchronous)는 서로 메시지를 주고받는 상대방이 어떤 방식으로 통신을 하는가에 대한 개념이다. I/O 통지모델에서 대화하는 주체들은 커널과 프로세스이다. 프로세스는 커널에게 I/O처리를 요청하고,커널은 프로세스에게 I/O 상황을 통지한다. 우선 I/O 요청은 반드시 동일하게 처리될 수 밖에 없는 부분이고, 결국에 커널이 프로세스에게 어떤 방식으로 통지하느냐에 따라 동기형이냐 비동기형이 결정될 것이다. 

동기형 통지모델의 프로세스는 커널에게 지속적으로 현재 I/O 준비 상황을 체크한다. 즉 커널이 준비되었는지를 계속 확인하여 동기화 하는 것이다. 따라서 동기형 통지모델에서 Notify를 적극적으로 진행하는 주체는 유저의 프로세스가 되며 커널은 수동적으로 유저 프로세스의 요청에 따라 현재의 상황을 보고한다. 

 

비동기형 통지모델

이와 반대로 비동기형 통지모델은 일단 커널에게 I/O작업을 맡기면 커널의 작업 진행사항에 대해서 프로세스가 인지할 필요가 없는 상황을 말한다. 유저의 프로세스가 I/O 동기화를 신경쓸 필요가 없기에 비동기형이라고 부를 수 있다. 따라서 비동기형 통지모델에서 Notify의 적극적인 주체는 커널이 되며, 유저 프로세스는 수동적인 입장에서 자신이 할일을 하다가 통지가 오면 그때 I/O 처리를 하게 된다. 



출처: https://ozt88.tistory.com/20?category=123069 [공부 모음]

설정

트랙백

댓글

Ethernet, IP, TCP, UDP Frame

통신/TCP_IP 2014. 10. 15. 14:23

------- Ethernet과 IP, TCP, UDP Header









------- Ethernet Frame


Ethernet frame은 다음과 같이 몇몇 타입이 있다.

- Ethernet II

- IEEE 802.3

- IEEE 802.2 Logical Link Control (LLC) frame

- IEEE 802.2 Subnetwork Access Protocol (SNAP) frame



--- Ethernet II


DEC, Intel, and Xerox에 의해 만들어졌으며,

DIX Ethernet 이라고도 불린다


첫 번째 필드엔 목적 MAC주소, 

두 번재 필드엔 보낸 MAC주소,

세 번째 필드엔 Ether type이라고 Ethernet 프로토콜 타입,

네 번째 필드엔 정보,

다섯 번째 필드엔 CRC(cyclic redundancy check) 또는 FCS(Frame Check Sequence)라고

오류 검출에 쓰인다.


(출처 : http://en.wikipedia.org/wiki/Ethernet_frame)






--- IEEE 802.3


Novell 사에서 IPX protocol용으로 만들어졌다.

Ethernet II와 흡사한 구조로 세 번재 필드인 EtherType 대신 Length 이다.







--- IEEE 802.2 Logical Link Control (LLC) frame


OSI 계층 구조에서만 사용하는 Frame으로 거의 사용하지 않는다.

토큰링이 이 구조를 사용한다.







--- IEEE 802.2 Subnetwork Access Protocol (SNAP) frame


OSI 계층 구조에서 사용한다. TCP/IP가 주류므로 OSI는 잘 사용하지 않는다.

AppleTalk이 이 구조를 사용한다.









--- IEEE 802.1Q tag

VLAN (virtual local area network) 서비스에 대한 규약으로 Ethernet frame 들에 포함하고 있는데,

데이타 링크 계층(TCP/IP) or 네트워킹 계층(OSI)인 라우터나 스위치 등에서 운영되는 것으로,

브로드캐스트 필터링, 보안, 주소 축약, 트래픽 흐름 관리, QoS 등에 사용된다고 한다.


VLAN은 Ethernet frame에 Source Address 와 EtherType 또는 Length fields 사이에 위치하고 있거나,

EtherType 또는 Length fields 에 위치하고 있다.

처음 2 byte (2 octets)에는 Tag Protocol Identifier (TPID) 값이 0x8100으로 되어 있다.









------- Ethernet Frame 구조체


linux 환경

/usr/include/linux/if_ether.h

/usr/include/net/ethernet.h

위치에서 확인할 수 있다




struct ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ unsigned short h_proto; /* packet type ID field */ };



struct ether_header { u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */ u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */ u_int16_t ether_type; /* packet type ID field */ };





--- 데이터 타입은

/usr/include/i386-linux-gnu/sys/types.h 에 있다.





--- ETH_ALEN 값은

/usr/include/linux/if_ether.h 에 있다.






--- type의 종류는

/usr/include/net/ethernet.h 에 있다.

더 많은 type은 /usr/include/linux/if_ether.h를 참고...














------- IP Header 구조체


http://en.wikipedia.org/wiki/IPv4 참고


/usr/include/netinet/in.h 에 프로토콜에 타입

/usr/include/netinet/ip.h 에 IP구조체가 정의 되어 있다



struct iphdr

{

#if __BYTE_ORDER == __LITTLE_ENDIAN

unsigned int  ihl:4;        //헤더 길이

unsigned int version:4;        //IP version 4

#elif __BYTE_ORDER == __BIG_ENDIAN

unsigned int version:4;        //IP version 4

unsigned int  ihl:4;        //헤더 길이

#else

# error "Please fix <bits/endian.h>"

#endif

u_int8_t    tos;

u_int16_t    tot_len;

u_int16_t    id;

u_int16_t    frag_off;

u_int8_t    ttl;

u_int8_t    protocol;

u_int16_t    check;

u_int32_t    saddr;

u_int32_t    daddr;

/* The options start here. */

};







------- TCP Header 구조체



/usr/include/netinet/tcp.h

/usr/include/linux/tcp.h

에 위치해 있다.


struct tcphdr

{

u_int16_t    source;        //source port

u_int16_t    dest;        //destination port

u_int32_t    seq;          //sequence number

u_int32_t    ack_seq;          //acknowledgement number

#if __BYTE_ORDER == __LITTLE_ENDIAN

u_int16_t    res1:4;           //(unused)

u_int16_t    doff::4;           //data offset

u_int16_t    fin:1;

u_int16_t    syn:1;

u_int16_t    rst:1;

u_int16_t    psh:1;

u_int16_t    ack:1;

u_int16_t    urg:1;

u_int16_t    res2:2;

#elif __BYTE_ORDER == __BIG_ENDIAN

u_int16_t    doff::4;           //data offset

u_int16_t    res1:4;           //(unused)

u_int16_t    res2:2;           //(unused)

u_int16_t    urg:1;

u_int16_t    ack:1;

u_int16_t    psh:1;

u_int16_t    rst:1;

u_int16_t    syn:1;

u_int16_t    fin:1;

#else

#error "Adust your <bits/endian.h> defines"

#endif

u_int16_t    window;        //window

u_int16_t    check;       //checksum

u_int16_t    urg_ptr;        //urgent pointer

};














'통신 > TCP_IP' 카테고리의 다른 글

HTTP 3핸드 쉐이킹 캡쳐  (0) 2020.10.12
TCP/IP 4 계층  (0) 2014.10.15

설정

트랙백

댓글

TCP/IP 4 계층

통신/TCP_IP 2014. 10. 15. 12:17


------- TCP/IP 4계층과 OSI 7계층




- TCP/IP 4계층은 인터넷 모델이라고도 한다.


 레벨

 계층

 기능

 4계층

 Application

응용 계층

프로토콜 : HTTP, FTP, Telnet, DNS, SMTP

OSI 7계층의 5, 6, 7계층에 해당한다.

TCP/IP 기반의 응용프로그램을 구분할 때 사용한다.

 3계층

 Transport

전송 계층

프로토콜 : TCP, UDP

OSI 7계층의 4계층에 해당한다.

통신 노드 간의 연결을 제어하고, 자료의 송수신을 담당한다.

 2계층

 Internet

인터넷 계층

프로토콜 : IP, ARP, RARP, ICMP, OSPF

OSI 7계층의 3계층에 해당한다.

통신 노드 간의 IP 패킷을 전송하는 기능 및 라우팅 기능을 담당한다.

 1계층

 Network Interface

네트워크 인터페이스 계층

프로토콜 : Ehternet, Token Ring, PPP

OSI 7계층의 1, 2 계층에 해당한다.

CSMA/CD, MAC, LAN, X.25, 패킷망, 위성 통신, 다이얼 업 모뎀 등 전송에 사용된다.

 


'통신 > TCP_IP' 카테고리의 다른 글

HTTP 3핸드 쉐이킹 캡쳐  (0) 2020.10.12
Ethernet, IP, TCP, UDP Frame  (0) 2014.10.15

설정

트랙백

댓글