Network - 3

TCP Socket Coding

  • TCP socket - server

    1
    2
    3
    4
    5
    6
    7
    8
    import socket

    serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    serv.bind(('localhost', 3030))
    serv.listen()
    data_sock, clnt_addr = serv.accept()
    data = data_sock.recv(1024)
    data
    • socket 클래스를 생성한다. AF_INET는 IPv4를, SOCK_STREAM은 TCP 방식을 의미한다.

    • bind() 메소드를 통해 IP와 port를 지정해준다.

    • 이 때 localhost는 127.0.0.1을 의미한다.

    • listen() 메소드를 통해 client가 접속하는 것을 기다린다.

    • 연결이 되면 accept() 메소드를 통해 데이터 통신용 소켓인 data_sock와 client의 주소 clnt_addr로 받는다.

    • data_sock.recv()를 통해 데이터를 받을 수 있다.

  • TCP socket - client

    1
    2
    3
    4
    5
    import socket

    clnt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    clnt.connect(('localhost', 3030))
    clnt.send('I am your father'.encode())
    • server socket과 마찬가지로 같은 방식으로 socket 클래스를 생성한다.

    • connect() 메소드를 이용하여 server와 같은 IP와 port를 지정한다.

    • send() 메소드를 이용하여 데이터를 송신한다.

  • server 쪽에서 데이터 통신용 소켓인 data_sock를 통해 send(), recv() 모두 가능하다.

  • client 쪽에서도 send(), recv() 모두 가능하다.

  • close()를 통해 연결을 종료힌다.

  • server는 serv와 data_sock 둘다 close 해야 한다.

  • client에서 connect만 하여도 되는 이유

    • OS가 자동적으로 IP(client의 host)와 port(ramdom)를 할당
  • connect() 메소드의 반환시점은 sever의 request Queue에 등록이 될 때

    • enqueue를 할 때
  • server와 다수의 client인 경우

    • server 쪽에서는 data_sock을 request Queue를 만들어 저장

    • 이 때, accept() 메소드에서 blocking이 걸림

    • 다른 데이터 소켓들은 데이터를 주고 받아야 하기 때문에 concurrency programming을 해야 함

    • concurrency programming

      • Multithreading, Multiprocessing 사용 - database는 아직도 multithreading 사용중

      • I/O Multiplexing - select, event-driven

      • linux에서의 epoll, window에서의 IOCP

TCP 헤더

  1. Source Port(송신) : 2bytes

  2. Destination Port(수신) : 2bytes

  3. Sequence Number : 4bytes

    • 이번에 보내는 데이터의 첫번째 바이트 순서 번호
  4. Acknowledgement Number : 4bytes

    • 수신하기를 기대하는 다음 바이트 번호

    • 마지막 수신 성공 순서번호 + 1

  5. Window : 2bytes

    • 상대편에게 자신의 버퍼 여유용량 크기를 지속적으로 통보하여 주는 기능

    • 데이터의 흐름을 컨트롤(flow control)

Sliding Window

  • TCP connection이 되면 server와 client의 TCB에 TCP 연결 처리에 필요한 정보가 들어있다.

  • TCB(Transmission Control Block)

    • server TCB 예시

      1. server의 IP와 port

      2. send buffer pointer

        • UNA

          • 송신했지만, 아직 승인되지 않은 첫 번째 데이터의 순서번호

          • Send Unacknowledged

        • NXT

          • 다음 차례의 sequence number
        • WND

          • 송신 윈도우 크기
      3. receive buffer pointer

        • NXT

          • 다음 차례에 받을 client(상대 host) sequence number
        • WND

          • 수신 윈도우 크기
    • client TCB 예시

      1. client의 IP와 port

      2. send buffer pointer - UNA, NXT, WND

      3. receive buffer pointer - NXT, WND

      • 여기서 수신 WND와 송신 WND의 크기는 같아야 한다.

      • 그리고 송신 WND의 크기가 주체가 된다.

      • 여기서 윈도우 크기는 수신 window 크기가 주체가 된다.

      • 받는 쪽이 먼저 크기를 알려줘야 송신이 그 크기로 보내기 때문이다.

      • 윈도우 크기로 데이터의 흐름을 컨트롤한다.(flow control)

  • send window

    • TCP 특성 상 데이터를 보내고 응답을 기다릴때까지 다음 데이터를 못보낸다.

      • 데이터를 주고 받는데 있어서 느릴 수 있다.
    • 그래서 send window 안에 usable window 개념이 있다.

      • send window 안에 다음과 같은 데이터 존재

        • 송신했으나 응답을 받지 못한 데이터(SENT + NOT ACK)

        • 아직 송신하지 않고 대기 중인 데이터(NOT SENT + READY)

          • 응답 받지 못한 데이터가 있더라도 보낼 수 있다.
    • SND.NXT와 RCV.NXT는 데이터를 주고 받을 때 값이 업데이트된다.

    • SND.UNA 경우, 수신 측에서 응답(ACK)을 받기 전까지는 절대 값이 업데이트되지 않는다.

    • 응답을 받으면 그 때 SND.UNA 값이 업데이트되면서 정해진 윈도우 크기가 옆으로 이동하게 된다.

    • 이렇게 윈도우 크기가 옆으로 이동하는 것을 슬라이딩 윈도우라고 한다.

  • TCP 약점(예시)

    1. send window 안에 데이터가 9byte가 있음

    2. 4byte를 먼저 보내고 5byte를 나중에 보냄

    3. Routing table이 변하여 처음 4byte를 보냈을 때보다 나중에 보낸 5byte가 먼저 도착

    4. 이 때 4byte가 도착하지 못하고 유실된 경우

    5. 5byte가 도착했다하더라도 다시 4byte의 데이터부터 다시 보내게 된다.

UDP(User Datagram Protocol)

  • 비 연결 지향형 프로토콜

  • 신뢰할 수 없다.

  • 데이터를 재전송하지 않는다.

  • 전송된 데이터 일부가 손실될 수 있다.

  • 동영상 및 게임 쪽에 사용

UDP Socket Coding

  • UDP socket - server

    1
    2
    3
    4
    5
    import socket

    serv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    serv = bind(('localhost', 3030))
    data_sock, clnt_addr = serv.recvfrom(1024)
    • SOCK_DGRAM은 UDP 방식을 의미한다.

    • bind() 메소드를 통해 IP와 port를 지정해준다.

    • serv.recvfrom()를 통해 데이터를 받을 수 있다.

  • UDP socket - client

    1
    2
    3
    4
    5
    import socket

    clnt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    serv_addr = ('localhost', 3030)
    clnt.sendto('I am your father!'.encode(), serv_addr)
    • 마찬가지로 같은 SOCK_DGRAM으로 생성한다.

    • sendto() 메소드를 이용하여 데이터를 송신한다.

  • server와 client 둘 다 sendto(), recvfrom() 메소드를 통해 데이터를 주고 받을 수 있다.

  • 신뢰성을 보장하지 않는다.

UDP 헤더

  1. Source Port(송신) : 2bytes

  2. Destination Port(수신) : 2bytes

  3. length : 2bytes. UDP 헤더와 데이터 필드를 모두 포함한 전체 패킷의 길이

응용 계층

  • FTP

    • 파일 전송을 위한 프로토콜로 보안이 취약
  • DNS(Domain Name System)

    • 도메인 이름을 IP 주소로 변환하는 프로토콜

      1
      $ nslookup [도메인 이름] # 명령어를 통해 IP를 알 수 있음
    • ex) www.google.com

      • DNS server가 뒤에서부터 com, google, www server를 통해 주소를 찾아낸다.

      • 한번 연결된 주소는 DNS 캐시에 남긴다.

      1
      2
      3
      4
      5
      ex) https://www.naver.com

      >> https : schema
      >> www : host
      >> naver.com : Domain Name
  • HTTP(HyperText Transfer Protocol)

    • 웹에서 데이터를 주고 받을 수 있는 프로토콜

HTTP/1.0 - 일시적 연결

  • 0.9 ~ 1.0까지 client와 server 간에 하나하나 데이터를 주고 받을 때마다 TCP를 연결하고 종료한다.

HTTP/1.1 - 지속적 연결(Keep Alive Connection[persistent connection])

  • 1.1부터는 TCP 연결을 닫지 않지 않고 그대로 유지 한다.

  • Connection: Close 헤더를 포함해 일시적 연결을 할 수 있다.

  • 캐싱

    • clientr가 첫 요청한 데이터를 저장

    • 재 요청시 내부에 저장해둔 파일을 사용하여 더 빠르게 서비스하기 위함

  • 프록싱

    • client와 server 사이에 위치

    • 사용자가 데이터를 요청했을 때, 프록시 서버로 요청

    • 프록시 서버는 해당 웹 서버로 가서 데이터를 주고 받음

    • 다시 프록시 서버를 통해 사용자에게 데이터를 가져오게 됨

    • 프록시 서버는 요청된 내용들을 캐시를 이용하여 저장

      • 캐시 안에 저장된 정보를 요구하는 요청에 대해 해당 서버에 접속하여 가져올 필요가 없음

      • 전송 시간을 절약할 수 있음(네트워크 병목 현상을 줄임)

    • 모든 데이터가 프록시 서버를 거치게 되므로 방화벽 역할

HTTP request header 구조

  • 컨텐트 협상

    • Accept로 시작하는 헤더는 컨텐츠 협상에 해당
    1. 서버 주도 협상

      • 항상 원하는 형식의 데이터를 받을 수 없음
    2. 에이전트 주도 협상

      • 원하는 데이터를 받을 수 있음

      • 자료 접근으로 두번의 요청과 응답이 필요함

        1
        2
        3
        ex) Accept-Language : kr;q=0.7, fr;q=0, en;q=0.4

        >> q 값을 다르게 줌으로써 가져오는 사이트의 언어를 결정한다.(0.7 = 70%)
  • Method

    • GET

      • 요청받은 URL의 정보를 검색하기 위해 서버 측에 요청

      • SELECT의 성격

    • POST

      • 요청한 URL에 폼(form) 입력을 처리하기 위함

      • 폼(form)과 함께 전송

      • 헤더 정보에 포함되지 않고 데이터 부분에 요청 정보가 들어감

      • INSERT의 성격

    • HEAD

      • GET 방식과 동일하나, 헤더 정보 이외에는 어떤 데이터도 보내지 않음

      • 웹서버 정보확인, 버젼확인, 최종 수정일자 확인 등의 용도로 사용

    • PUT

      • POST와 유사한 전송 구조를 가짐

      • 헤더 이외에 메시지(데이터)가 함께 전송

      • UPDATE의 성격

      • PUT vs PATCH

        • PUT은 항상 모든 필드 값을 바꾸지만, PATCH는 해당하는 필드 부분만 바꿈
    • DELETE

      • 요청된 소스를 삭제할 것은 요청
    • TRACE

      • 서버에 루프백 메세지를 호출하기 위해 사용

HTTP response header 구조

  • 상태 코드

    • 1xx : 정보

    • 2xx : 성공

    • 3xx : 리다이렉션

    • 4xx : 클라이언트 오류

    • 5xx : 서버 오류

  • 청킹(chunking)

    • Content-Length

      • response header에 정의

      • 요청한 내용에 대한 실제적인 결과인 body의 길이가 몇 bytes인가를 의미

      • 즉, 읽어야 할 body의 크기를 알려줄 때 사용

    • Transfer-Encoding: chunked

      • 덩어리(Chunk)의 나열로 데이터를 전송하는 HTTP 1.1 데이터 전송 방법 중 하나

      • 동적으로 생성한 콘텐츠인 경우, 전체보다 덩어리 단위로 쪼개서 보냄

      • 따라서 전체 콘텐츠의 크기를 알려주지 않아도 됨

Share