공부중

[TCP/IP] TCP 기반 서버 / 클라이언트 - 1 본문

Programing/TCP IP 소켓

[TCP/IP] TCP 기반 서버 / 클라이언트 - 1

곤란 2013. 1. 29. 20:07
반응형

 

TCP와 UDP

 

○TCP/.IP 프로토콜 스택

TCP/IP 스택 이 4개의 계층으로 나뉜다 이로 데이터 송수신의 과정을 네 개의 영역으로 계층화 했다는 의미 이다.

 

인터넷 기반의 효율적인 데이터 전송을 하나의 큰 프로토콜 설계로 해결한 것이 아닌 작게 나눠서 계층화 하려는 노력이 시도 끝에

TCP/IP프로토콜 스택이 나왔다

 

그래서 TCP 소켓을 생성해 데이터를 송 수신할 경우 위의 그림과 같이 4개의 계층으로 통해 데이터를 송수신 하게 된다.

 

그러나 UDP소켓을 생성하여 데이터를 송수신할 경우 다음 네 계층을 통해 데이터를 송 수신 하게 된다.

 

이러한 각각 계층은 OS와 같이 소프트웨어 혹은 NIC같은 물리 장치가 담당한다.

 

○ LINK 계층

LINK계층은 물리적인 영역의 표준화에 대한 결과이다.

가장 기본이 되는 영역이다

LAN,WAN,MAN과 같은 네트워크 표준과 관련된 프로토콜을 정의하는 영역.

두 호스트가 인터넷을 통해 데이터를 주고 받을 때

물리적인 연결이 있어야 하므로 이 부분에 대한 표준이 LINK계층에서 담당한다.

 

○ IP 계층

IP는 목적지로 데이터를 전송하기 위해 어떤 경로를 거쳐갈 것인지를 해결해 준다.

IP자체는 비 연결지향적이며 신뢰를 할 수 없는 프로토콜이다.

데이터를 전송할 때 마다 거쳐야 할 경로를 선택해 주지만 경로가 일정하지 않다.

전송도중 경로에 문제 발생시 다른 경로를 선택하는데 이 과정에서 데이터가 손실되거나 오류가 발생하는 문제가 생겨도 해결해 주지 않는다.

 

오류발생에 대한 대비가 없는 프로토콜이 IP이다.

 

○ TCP와 UDP 계층

TCP와 UDP는 IP계층에서 알려준 경로를 가지고 데이터의 실제 송수신을 담당한다.

이 계층을 전송(Transport)계층이라고 한다.

TCP는 신뢰성 있는 데이터의 전송을 담당한다. 그러나 TCP가 데이터를 보낼 때 기반이 되는 프로토콜이 IP이다.

 

IP만 이용해서 데이터를 전송할 때 예로 A와 B 그리고 C순서로 전송 했을시

A패킷보다 늦게 보낸 B패킷이 먼저 도착할 수도 있고 A와 C만 도착 할 수도 있으며 일부 패킷은 손상도 될 수 있다.

 

그러나 여기에 신뢰성이 있는 TCP가 있다면 어떻게 될까?

TCP는 확인 절차를 걸쳐서 신뢰성이 없는 IP에 신뢰성을 부여해준 프로토콜이다.

 

○ APPLICATION 계층

소켓이라는 도구가 프로그래머에게 주어지고 이것을 이용해 만드는 과정에서

클라이언트와 서버와의 데이터 송수신 규칙이 자연스레 만들어 질 것이다.

이것이 APPLICATION프로토콜 이라고 한다.

 

TCP기반 서버& 클라이언트

○ TCP 서버에서의 기본적인 함수 호출 순서

대부분의 TCP 서버 프로그램은 다음과 같이 이 순서로 구현 된다.

 

socket( )

    소켓 생성

 

bind( )

    소켓의 주소 할당

 

listen( )

    연결요청 대기

 

accept( )

    연결을 허용

 

read( ) 또는 write( )

    데이터 송수신

 

close( )

    연결 종료

 

먼저 socket 함수의 호출을 통해 소켓을 생성하고 주소 정보를 담기 위해 bind함수를 호출해 소켓에 주소를 할당한다.

 

○ 연결요청 대기상태

bind함수로 소켓에 주소까지 할당했으면 listen함수를 통해 연결요청 대기상태로 해 주어야 한다.

listen 함수가 호출 되어야 클라이언트가 connect함수를 호출할 수 있다.

connect 함수가 listen 함수보다 먼저 호출 시 오류가 발생한다.

#include <sys/type.h>

int listen(int sock, int backlog);

성공 시 0, 실패시 -1 반환

  • sock

연결요청 대기 상태에 두고자 하는 소켓의 파일 디스크립터 전달, 이 함수의 인자로 전달된 디스크립터의 소켓이 서버 소켓(리스닝 소켓)이 된다.

  • backlog

연결요청 대기 큐(Queue)의 크기 정보를 전달

ex) 5 전달시 클라이언트 연결요청을 5개까지 대기 가능

 

 

연결 요청 대기 큐라는 것은 말 그대로 연결을 요청하기 위해서 줄을 선 것으로 보면 된다.

서버가 연결요청 대기 상태에 있을 때라는 것은

클라이언트가 연결요청 했을 때 연결이 수락 될 때까지 연결요청 자체를 대기 시킬 수 있는 상태를 말한다

 

○ 클라이언트의 연결요청 수락

클라이언트의 연결 요청이 들어왔다면 들어온 순서대로 연결요청을 수락해야 한다.

연결요청이 수락 되면 클라이언트와 데이터를 주고 받을 수 있는 상태가 된다.

 

물론 이러한 데이터를 주고 받기 위해서 소켓이 필요하지만 이미 서버 소켓은 연결요청을 담당하고 있다.

그러나 이 서버소켓을 대신해서 accept함수의 호출로 만들어진 소켓이 자동으로 클라이언트와 연결이 되며

내부적으로 데이터 입출력에 사용할 소켓을 생성하고 그 소켓의 파일 디스크립터를 반환한다.

 

#include <sys/socket.h>

int accept(int sock, struct sockaddr * addr, socklen_t * addrlen);

성공 시 생성된 소켓의 파일 디스크립터, 실패 시 -1 반환

  • sock

서버 소켓의 파일 디스크립터 전달

  • addr

연결요청을 한 클라이언트의 주소 정보를 담을 변수의 주소 값 전달, 함수 호출이 완료되면 인자로 전달된 주소의 변수에는 클라이언트의 주소 정보가 채워진다.

  • addrlen

두 번째 매개변수 addr에 전달된 주소의 변수 크기를 바이트 단위로 전달, 단 크기정보를 변수에 저장한 다음 변수의 주소 값을 전달, 그리고 함수호출이 완료될시 크기 정보로 채워져 있던 변수에는 클라이언트의 주소 정보 길이가 바이트 단위로 계산 되어 채워짐.

 

연결요청 대기 큐에 있는 연결요청 하나를 꺼내서 새로운 소켓을 생성한 뒤에 연결요청을 완료 한다.

 

○TCP 클라이언트의 기본적인 함수 순서

socket( )

    소켓 생성

 

connect( )

    연결요청

 

read( ) 또는 write( )

    데이터 송수신

 

close( )

    연결 종료

 

서버에 비해서 매우 간단하다.

소켓을 만들고 연결요청이 끝이기 때문이다.

 

서버에서 listen함수를 호출한 뒤로 연결요청 대기 큐를 만들어 놓기 때문에 그 이후부터 클라이언트가 연결요청이 가능해진다.

 

클라이언트는 다음 함수를 이용 해서 호출한다.

#include <sys/socket.h>

int connect(int sock, const struct sockaddr * servaddr , socklen_t addrlen);

성공 생성된 소켓의 파일 디스크립터, 실패 시 -1 반환

  • sock

클라이언트 소켓의 파일 디스크립터 전달

  • servaddr

연결요청을 할 서버의 주소정보를 담은 변수의 주고 값 전달. 함수호출이 완료되면 인자로 전달된 주소의 변수에는 클라이언트의 주소 정보가 채워진다.

  • addrlen

두번째 매개변수 servaddr에 전달된 주소의 변수 크기를 바이트 단위로 전달, 단, 크기정보를 변수에 저장한 다음에 변수의 주소 값을 전달한다. 그리고 함수호출이 완료되면 크기 정보로 채워져 있던 변수에는 클라이언트의 주소 정보 길이가 바이트 단위로 계산되어 채워진다.

 

클라이언트가 connect함수를 호출시 다음 둘중 한가지 상황이 되어야 함수가 반환을 한다.

  • 서버에 의해 연결요청이 접수 되었다.
  • 네트워크 단절등 오류상황이 발생하여 연결요청이 중단 되었다.

연결요청의 접수는 서버의 accept함수호출을 의미하는 것이 아닌 연결요청 정보가 연결요청 대기 큐에 등록된 상황을 의미한다.

그러므로 connect함수가 값을 반환 하여도 바로 서비스가 이루어 지지 않을 수도 있다.

 

 

○TCP기반의 서버와 클라이언트의 함수 호출 관계

서버는 소켓 생성 이후 bind, listen 함수의 연이은 호출을 통해 대기상태에 들어간다.

클라이언트는 connect 함수호출을 통해서 연결요청을 하게 된다.

클라이언트는 서버 소켓의 listen함수 호출 이후에 connect함수호출이 가능하다.

또한 클라이언트가 connect함수를 호출하기에 앞서 서버가 connect 함수를 호출하기 전에 accept함수를 먼저 호출 할 수도 있다.

 

 

 

반응형