2020-01-14 TIL

5Fs

  1. Fact
  2. 채팅 서버를 만들때 TCP는 fork를 사용하고, 왜 UDP는 사용하지 않을까 ?

    1. TCP

      1. TCP는 서로 통신을 하기 위해서 그들만의 통신 경로를 얻기 위해 three handshake를 한다.
      2. socket() -> bind() -> listen() -> accept() 순서로 실행된다.
      3. 그 이후 클라이언트가 connect 요청을 하면 서버에서 accept 함수가 대기하고 있다가 실행된다. accept 함수는 통신을 위한 소켓을 반환하고, 반환된 소켓을 이용하여 클라이언트와 통신을 주고 받는다.
      4. TCP 서버는 현재 connect를 요청해주는 것이 책임이기 때문에, 다른 이외의 일을 수행하지 못함.
      5. 그렇기 때문에, 서버는 클라이언트의 connect 요청을 accept 함수로 받은 후에 fork를 사용하여 자신의 프로세스를 복사한다.
      6. 자식 프로세스에서는 클라이언트와 연결을 처리만 하기 위해서, 부모에서 물려받은 accept된 상태의 socket을 없앤다.
      7. 부모는 자식에게 위의 일을 위임하고, 자신의 일만(클라이언트의 connect만 받기 위해) 하기 위해서 fork하기 전 accept로 받은 클라이언트와의 연결 소켓을 지운다.
    2. UDP

      1. UDP는 TCP와 같이 각각의 통신경로가 필요없기 때문에 3 hand shake를 할 필요가 없다.
      2. 그렇기 때문에, 서버는 한소켓을 가지고 recvFrom 함수로 많은 클라이언트로 부터 메시지 받을 수 있다.
      3. 클라이언트 또한 연결을 맺을 필요 없기 때문에, 한 소켓으로 여러 서버에 메시지를 전송할 수 있다.
      4. 하지만, recvFrom은 udp datagram이 올 때 까지 holding 된다. 그러므로 sendTo 후에 응답이 늦게된다면, 멈춘 상태일 것이다. 결국엔 UDP도 받는 소켓과, 보내는 소켓이 따로 필요하므로, fork를 사용해야한다.
  3. 그렇다면 TCP 서버에서는 fork를 하고 있지만 UDP는 서버에 fork하지 않고 있다. UDP 에서 client에서 fork하는데 왜그럴까 ?

    1. TCP

      • 위에서 이야기한것과 같이 TCP는 각각 클라이언트만의 전용통로를 만들기 위해 3handshake를 해야하고, 서버에서는 accept를 사용하여 연결 소켓을 반환해준다.
      • 이상황에서 포크를 하고 자식프로세스에선 듣기 소켓을 지우고, 부모 프로세스에선 연결 소켓을 지운다.
    2. UDP

      • 데이터가 무결성 있게 전송 된다는 것을 보장 하지 않는다.
      • 그렇기 때문에, 서버는 recvFrom 한 후에, 클라이언트에게 바로 전송이 가능하기 때문에 fork 를 할 필요가 없다.
      • 하지만 클라이언트에서는 서버로 전송할 입력값을 받는 프로세스는 홀딩된다는 문제가 있다 그렇기 때문에, 다른 프로세스를 사용해서 서버로 부터 오는 메시지를 받기 위해 recvFrom 를 실행 시켜줘야한다.
      • 그럼 fork를 하는 시점은 udp 소켓에 필요한 변수를 정의 한 후에 한다.
      • 부모는 입력을 받고, 자식은, recvFrom으로 서버로 부터 오는 메시지를 받는다.
      • 그러고, 부모가 끝나면 자식 process도 꺼주게 되는것이다.

Written by@Zero1
This blog is for that I organize what I study and my thinking, feeling and experience.

GitHub