HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📖
공부한 책
/
📒
Computer Systems - A Programmer’s perspective
/
11. Network Programming

11. Network Programming

Client-Server Programming Model

  • 모든 네트워크 어플리케이션은 client-server model에 기반을 두고 있음
  • server는 resource를 관리하고 그 resource를 조작하여 클라이언트에게 어떠한 서비스를 제공함
  • client-server 모델의 근본적인 operation은 transaction임(db transaction이랑은 전혀다름)
      1. client가 서비스가 필요할 때 request를 보냄(transaction 시작)
      1. 서버가 request를 받고 resource를 조작함
      1. 서버가 client에게 response를 보내줌(웹 서버가 클라이언트에게 파일 보내주는)
      1. 클라이언트가 response를 받고 그것을 조작함(렌더링~~)

Networks

Global IP Internet

  • TCP/IP는 사실 프로토콜의 집합임. 각각은 다른 기능을 제공함
    • IP 프로토콜은 기본적인 네이밍 스킴과 패킷(known as datagrams)을 보낼 수 있는 배송 메커니즘을 제공함
      • IP 프로토콜은 기본적으로 패킷이 손실되거나 복제되었을 때에 회복하려는 노력을 전혀 하지 않기에 믿을만 하지는 않음
    • UDP(Unreliable Datagram Protocol) 은 IP 프로토콜을 아주 약간 확장한 것으로 패킷을 프로세스에서 프로세스로 전달함. host에서 host가 아닌
    • TCP는 IP 프로토콜 위에 뭘 더 얹어서 만든 복잡한 프로토콜로 프로세스 간에 reliable full duplex (bidirectional) 연결을 맺음

Internet Connections

  • 인터넷의 클라이언트와 서버는 byte stream을 전송하고 받음으로써 통신하게 되는데 이 때 connection이 필요함
  • connection은 프로세스 각각을 연결하고, full-duplex임(data가 양방향으로 동시에 흐를 수 있다는 것)
  • 또한 신뢰성이 있음 (source process에서 보낸 byte stream의 순서대로 목적지 프로세스에서 그대로 받아짐)
  • socket은 connection의 end point이고, 각각의 socket은 해당하는 socket address를 갖고 있음
    • socket address : IP 주소 & port 로 이루어짐
    • ephemeral port : 클라이언트 소켓의 포트는 connection request를 만들 때 커널에 의해 포트가 자동으로 설정됨
  • connection은 양 끝단의 socket address pair로 고유하게 식별됨
    • (cliaddr: cliport, servaddr: servport)
    • notion image

Sockets Interface

 
  • socket interface는 Unix I/O 함수들과 같이 쓰이는 함수의 집합으로 네트워크 어플리케이션을 구성할 때 사용됨
  • Unix kernel의 관점에서는 socket은 커뮤니케이션의 endpoint이고 Unix program의 관점에서는 socket은 해당하는 descriptor를 가진 file로 보이게 됨
    • notion image

      socket

    • socket descriptor를 만들기 위해서 클라이언트와 서버에서 사용하는 함수
    • socket 함수에서 반환된 descriptor는 아직 부분적으로만 open 된 것이고 read나 write를 할 준비는 되지 않음
    • client 쪽이냐 서버 쪽이냐에 따라 socket open의 과정이 달라짐
    • 디폴트로, 커널은 해당 함수에 의해 생성된 descriptors를 클라이언트 쪽에서 쓰이는 active socket이라고 가정함. listen 함수가 호출될 시 server 쪽의 소켓으로 인지함
    • Client

      connect — client 쪽

      • 클라이언트는 해당 함수를 호출하면서 서버와의 커넥션을 맺음
      • 커넥션이 성공적으로 맺어지고 나면 read와 write를 할 수 있고 커넥션은 socket pair로 나타내어 질 수 있음
        • (cliaddr: cliport, servaddr: servport)

      open_clientfd

      • 위의 두 함수를 묶어주는 함수로써 클라이언트가 서버와 커넥션을 맺기 위해 사용하는 함수임
      • 커넥션이 성공적으로 맺어질 시, socket descriptor를 반환하게 되고 해당 socket descriptor에 대해 Unix I/O를 이용하여 서버와 통신을 할 수 있음
      Server

      bind

      • server의 socket address를 socket descriptor에 bind 해주는 역할

      listen

      • 해당 함수를 호출함으로써 서버에서 쓰이는 소켓이라고 커널이 인식하게 됨
      • active socket → listening socket 으로 변환, 클라이언트로부터 커넥션 요청을 받을 수 있게 됨

      open_listenfd

      • 서버가 사용할 수 있는 listening descriptor를 반환하게 됨. socket, bind, listen을 wrapping한 함수

      accept

      • 클라이언트로부터 커넥션 요청이 들어오기를 기다림
      • listening descriptor로 요청이 들어오면 클라이언트 socket address 필드에 값을 채워 넣음
      • connected descriptor를 반환하게 됨
      💡
      Why the distinction between listening and connected descriptors? 두개의 descriptor를 구분 함으로써 클라이언트 커넥션을 동시에 많이 처리할 수 있는 concurrent server를 만들 수 있음. connection request가 listening descriptor에 도착할 때마다 process를 만드는 식으로. 계속 듣고 있고, 사용할 것은 connected descriptor로 사용한다는 의미인듯
struct sockaddr { unsigned short sa_family; /* Protocol family */ char sa_data[14]; /* Address data */