CS/네트워크 수업 / / 2021. 3. 23. 02:15

컴퓨터 네트워크 4주차


Transport Layer Review

  • 트랜스포트 계층은 호스트에서 동작 중인 애플리케이션 프로세스들 간의 논리적 통신을 제공. 여기서 말하는 논리적 통신이란 애플리케이션 관점에서 보면 프로세스들이 동작하는 호스트는 직접 연결된 것처럼 보인다는 뜻이다. 그래서 트랜스포트 계층 프로토콜은 네트워크 라우터가 아닌 End-System에서 구현된다.
  • 세그먼트: 트랜스포트 계층에서 전송되는 패킷 명칭
  • 만약 애플리케이션에서 보낸 메시지 길이가 길어서 세그먼트에서 지원하는 길이를 초과하면 두 개 이상의 세그먼트로 쪼개서 데이터를 전송해야 할 것이다.
  • 다중화 및 역다중화를 구현하기 위해 포트 번호 사용(호스트 내에서 unique하게 부여) → IP주소 + port

Multiplexing(다중화)

  • 소켓으로부터 네트워크 계층으로 캡슐화해서 보내기(집 안의 우편물 합쳐서 우편부에게)
  • 여러 흐름이 있을 때, 그 흐름들을 하나의 흐름으로 묶어서 처리. 즉, 데이터를 보내지 전에 모으는 것
  • 네트워크 계층은 서로 다른 호스트 간에 데이터그램을 전송하기 위한 계층
  • 트랜스포트 계층은 호스트에 존재하는 여러 개의 소켓 간에 데이터를 전달하기 위한 계층
    • 하나의 IP로 들어온 패킷을 여러 개의 소켓 중 어느 소켓으로 전달할 것인지?
    • 역다중화
  • 여러 개의 소켓으로부터 들어오는 패킷을 서로 공유하는 네트워크 계층을 통해 전송
    • 소켓은 애플리케이션 계층과 트랜스포트 계층 사이에 데이터를 주고 받는 통로 역할을 한다. 트랜스포트 계층은 애플이케이션에서 데이터를 받고 이 데이터를 다시 조각내서 세그먼트로 만들고 각 세그먼트에 헤더 정보를 넣는다. 이 캡슐화된 세그먼트들을 네트워크 계층으로 전달하는 과정을 '다중화'라고 한다.

Demultiplexing(역다중화)

  • 네트워크 계층으로부터 해당 소켓으로 디캡슐화해서 보내기(집 안의 담당자가 수신자들에게 우편물 나눠주기)
  • 하나의 흐름으로 묶여서 온 흐름들을 다시 여러 흐름으로 나누어 줌. 즉, 데이터를 받은 다음, 각 애플리케이션에 나누어 준다.
  • Connectionless demux(UDP): segment의 dest IP + dest port를 검사해서 dest 소켓에게 전달한다. 두 개의 UDP segment들이 sourct IP나 port가 하나 혹은 둘다 다르더라도 동일한 목적지 IP와 port를 갖는다면 동일한 애플리케이션 socket을 통해 process에 전달된다
  • Connection-oriented demux(TCP): TCP 소켓은 4개 튜플(출발지 IP주소, 출발지 포트번호, 목적지 IP주소, 목적지 포트번호)로 된 집합에 의해 식별 (이 4개의 값 중 하나라도 다르면 다른 소켓과 매칭이 된다)→ 네트워크로부터 호스트에 TCP 세그먼트 도착. TCP 같은 경우는 socket을 열 때, 자신의 IP와 port 뿐만 아니라 상대방(자신과 통신하는 프로세스)의 IP와 port를 모두 가지고 있어야 한다. TCP는 1:1로 통신하도록 디자인 되었기 때문에 애플리케이션이 항상 1:1로 통신한다. 그렇기 때문에 소켓 하나당 하나의 프로세스와 통신하기 때문에 애플리케이션이 목적지를 찾을 필요가 없다. UDP는 다중 접속이 되도록 디자인이 되었기 때문에 UDP에서는 여러 개의 클라이언트와 통신을 하므로, 애플리케이션의 목적지를 찾아 정해주는 역할을 반드시 해야한다.

4개의 값(source IP, source port, dest IP, dest port) 중 한 개만 달라도 다른 소켓으로 취급된다. (프로세스를 분화하는 게 아니라 스레드로 분화함으로써 서버의 자원을 아낀다)

Connectionless transport: UDP(User Datagram Protocol)

  • 아주 기본적인 기능만 하는 전송 계층 프로토콜
  • best effort(최선형 서비스): 데이터를 전송하는데 최선을 다하겠지만 완전한 전송에 어떠한 보장할 수는 없다. → UDP Segment가 손실될 수 있고 손실이 돼도 복구하지 않는다. 또한, 애플리케이션에 배달할 때 Segment의 순서에 관계없이 전송한다.(Segment 순서가 상관없는 서비스가 적합)
  • Connectionless(사전 연결 설정 작업이 없다)
    • No handshaking: TCP는 데이터 전송을 하기 전에 3-Way-handshake(상대방 프로토콜에게 연결 의사나 통신 의사가 있는지 물어보는 작업) 작업을 통해 사전에 연결 설정을 하는 반면, UDP는 연결이 돼어 있는지 확인만 되면 데이터 전송을 시작한다. e.g. 우편 서비스
    • 각 UDP Segment는 다른 Segment와는 독립적으로 취급된다. 즉, 순서에 상관없이 데이터를 보내주기만 하면 되는 서비스에 적합하다. e.g. 스트리밍 멀티미디어 서비스(손실이 조금 일어나더라도 서비스 운영에는 지장이 없다. 하지만 속도는 중요하다), DNS, SNMP(Simple Network Management Protocol, 네트워크를 관리하는 프로토콜)
    • UDP 프로토콜에서 신뢰성을 어떻게 제공해줄 수 있을까? 여기서 말하는 신뢰성이란 데이터 손실이 발생했을 때, 재송신해주고 데이터 오류가 발생했을 때, 오류 처리를 해주는 것을 말한다. UDP에서 신뢰성을 제공하려면 애플리케이션 계층에서 제공해줘야 한다. 즉, 애플리케이션에서 특정 에러에 대한 처리를 해야 한다!! UDP 자체에서는 신뢰성 있는 통신을 제공하지 않기 때문에....

    • 위의 UDP segment 포맷에서 payload에는 상위 층에서 data가 담긴다.
    • checksum 필드는 에러가 난 segment을 찾을 수 있는 필드. UDP에서는 에러를 수정하지는 않지만 에러가 나면 바로 segment를 폐기한다.
    • 왜 UDP를 사용하나?
      • no connection establishment: 사전 연결 설정을 하는 작업이 없으므로, 연결을 마칠 때 하는 작업 역시 없다. 연결 설정 작업이 없기 때문에 딜레이가 발생하지 않는다.
      • 송신자와 수신자 간에 연결 상태 정보를 관리하지 않는다
      • 헤더 사이즈가 작다.
      • UDP의 경우는 혼잡 제어를 하지 않으므로, 혼잡 상황이 돼서 버려질 경우에는 그냥 Segment를 버린다. 그래서 UDP는 원하는 만큼 빨리 서비스를 할 수가 있다.
    • UDP의 checksum 필드에 대해서 알아보자
      • 전송된 Segment에 발생한 오류를 찾는 데 그 목적이 있다.
      • 우선 sender는 Segment의 header와 payload를 16 bit씩 쪼개진 단위로 인식한다. 그런 다음, 연속된 16bit segment 내용을 두 개씩 전부 더해준다. 즉, 처음 두 개의 16bit segment를 더하고 그 결과를 다음 16bit segment와 더하고를 반복... 이렇게 모두 다 더한 최종 합의 1의 보수를 취한다. 전체 다 더한 1의 보수를 취한 checksum 값을 UDP checksum 값에 저장해서 전송!!!!
      • receiver가 전체 segment을 받으면 이번에 receiver가 sender가 한 작업을 그대로 진행한 다음 도출한 checksum값을 받은 checksum값과 일치하는지 비교한다. 에러가 없으면 일치해야 겠지만, 일치하지 않으면 어디에선가 오류가 발생한 것이므로 해당 segment를 폐기한다. → checksum 값에 이상이 없더라도 낮은 확률로 다른 곳에서 에러가 발생할 수 있으므로 좀 더 정확히 에러 체킹을 하기 위해서는 애플리케이션 레이어에서 더 정교하게 에러 체킹 알고리즘을 짤 필요가 있다.

      • 16 bit의 segment content의 덧셈 간에 Most Significant bit에 올림 비트가 발생하면 해당 비트는 결과값의 맨 마지막 비트에 더해준다.

principles of reliable data transfer(신뢰성이 있는 데이터 전송을 위한 원리)

애플리케이션 레이어에서 sending process가 데이터를 트랜스포트 레이어에 넘겨줄 때, 트랜스포트 레이어가 신뢰성 있는 데이터 채널이면 데이터 손실이나 변형없이 receiver에 도착할 것이다. 하지만 트랜스포트 레이어에서 사용하고 있는 채널 자체가 신뢰성이 없는데 신뢰성있는 채널을 제공해주려면 트랜스포트 레이어에 있는 프로토콜에서 신뢰성을 확보해야 한다. 그래서 위 템플릿에 보는 바와 같이 트랜스포트 레이어에서 신뢰성 처리를 위해서 별도로 신뢰성 프로토콜을 구축한 것을 볼 수 있다.

  • rdt_send(): 애플리케이션 레이어에서 데이터를 receiver의 애플리케이션 레이어에 전달하기 위해 호출. 데이터를 트랜스포트 레이어에 전달. 그러면 rdt(reliable data transfer)가 받아서 rdt 프로토콜이 udt_send() 함수를 호출
  • udt_send(): send-side에 있는 데이터를 패킷으로 만들어서 unreliable channel을 통해서 receiver까지 전달.
  • rdt_rcv(): 수신 측, rdt에서 데이터 수신
  • deliver_date(): 애플리케이션 레이어에 수신 받은 데이터 전달r_date(): 애플리케이션 레이어에 수신 받은 데이터 전달

  • unreliable 채널은 비트 에러와, 패킷 손실이 발생할 수 있다.
  • sender는 상위층으로부터 call을 기다린다. 즉, red_send(data) 이벤트가 발생하면 데이터를 가지고서 패킷을 만들고 underlying channel에다가 패킷을 보내고 다시 call을 기다린다.
  • receiver는 아래쪽 채널(unreliable channel)로부터 패킷을 받을 때까지 대기하고 있다가 패킷을 수신하면 이벤트가 발생한다. 패킷이 도착하면 rdt_recive(packet)이 호출되고, 패킷으로부터 데이터를 추출하고 deliver_data(data)를 호출하고 다시 하위 채널로부터 패킷 수신 상태로 돌아간다.

만약 패킷에 bit error가 있으면 어떻게 대응해야 할까?

여기서 말하는 bit error라는 것은 비트가 flip, 즉 뒤집힌 것(0→1, 1→0)을 말한다. 비트가 뒤집힌 경우에 checksum 기법 같은 에러 발견 기법을 사용해 우선 에러를 찾으면, 사람들이 대화 중에 상대방 말을 잘못 들으면 '다시 말해주세요' 라고 요청하는 것과 같이, 데이터 통신에서도 재전송 요청을 한다. 재전송 요청을 할 때 사용하는 매커니즘이 acknowledgements(ACKs)와 negative acknowledgements(NAks) 이다.

  • acknowledgements(ACKs): 수신 측이 명시적으로 송신 측한테 패킷을 잘 수신했다고 메시지 전달.
  • negative acknowledgements(NAKs): 수신 측이 명시적으로 송신 측한테 패킷에 에러가 발생했다는 메시지 전달. 만약 송신 측에서 NAKs를 수신하면 데이터를 패킷을 재송신한다.
  • rdt1.0 → rdt2.0 으로 넘어오면서 추가된 기능
    • 에러 탐지
    • 피드백(ACK, NAK): 패킷을 잘 받았는지, 패킷에 에러가 있는지

  • sender: rdt1.0에서는 상위 층으로부터 콜을 기다리고 있다가 rdt_send(data) 함수가 호출되면 data에 checksum으로 헤더를 붙여서 패킷을 만들고 udt_send(sndpkt)을 호출하고 다시 다른 데이터를 받기 위해 waiting 상태로 돌아갔다면, rdt2.0에서는 패킷을 전송하고 ACK나 NAK를 기다려야 하기 때문에 상태를 ACK나 NAK를 기다리는 상태로 머신 상태를 변경해야 한다. ACK나 NAK를 기다리는 머신은sender로부터 전송된 패킷을 수신하고 수신받은 패킷의 정보가 NAK이면 sender로 동일 패킷을 재전송하고 다시 ACK나 NAK를 받기 위해 기다리고, 수신 받은 패킷의 정보가 ACK라면 애플리케이션 층으로부터 다음 데이터를 받기 위해 상태를 변경하고 기다린다.
  • receiver: 하위 층으로부터 데이터 패킷을 수신하고, 해당 데이터 패킷에 에러가 있으면 NAK를 전송하고 다시 패킷 수신을 위해 대기한다. 반대로 receive 패킷이 Not corroupt 패킷이라면 패킷에서 데이터를 뽑아서 애플리케이션 계층에 전달하고, udt_send(ACK)를 sender 측에 전송한 후에 다시 다음 패킷을 수신하기 위해 상태를 ready로 변경한다.ㄴ

rdt2.0의 치명적인 오류: 만약 ACK나 NAK에 오류가 발생할 때 어떻게 해야할까? → rdt2.1

송신 측에서 패킷을 전송하고 받은 패킷이 ACK였는데, 이 패킷이 오류가 발생해서 ACK인지 NAK인지 모른다면? ACK인지 NAK인지 모르기 때문에 송신 측은 함부로 패킷을 재전송할 수가 없다. 왜냐하면 NAK로 판단해서 동일 패킷을 재전송 한다면 수신 측은 동일 패킷을 상위 레이어에 또 한 번 올리는 꼴인데, 그러면 전체적인 데이터가 깨질 수가 있다. 그렇기 때문에 수신 측에서는 송신 측이 동일 패킷을 재전송할 수 있으므로 수신받은 패킷이 복사본 패킷인지 아닌지 판단할 수 장치가 필요하다. → Sequence Number

Sequnce Number

sender는 ACK나 NAK에 오류가 발생하면 현재 패킷을 재전송하는데, 이 때 패킷에는 해당 패킷이 몇 번째 패킷인지 알 수 있는 Sequence Number가 있기 때문에 설령 동일 패킷을 재전송 했더라도 receiver 측에서 복사본 패킷을 필터링할 수 있다. 이렇게 처리하는 방식을 stop and wait 방식이라고 하는데 stop and wait 방식은 현재 패킷과 그 다음 패킷만 구분할 수 있으면 되기 때문에 1bit 필드를 사용한다. 즉 현재 보내는 패킷의 시퀀스 번호가 0번이면 다음 패킷은 1번, 그 다음 패킷은 다시 0번... 이런 식으로 흘러간다.

'CS > 네트워크 수업' 카테고리의 다른 글

컴퓨터 네트워크 6주차  (0) 2021.04.07
컴퓨터 네트워크 5주차  (1) 2021.03.29
컴퓨터 네트워크 3주차  (1) 2021.03.23
컴퓨터 네트워크 2주차  (1) 2021.03.23
컴퓨터 네트워크 1주차  (0) 2021.03.23
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유