본문 바로가기
일상,취미

다시 시작하는 TIL 16일차

by 진득한진드기 2024. 6. 28.

오늘 한일 

오늘은 이미 미러링 되고 있는 기기에서 다른 클라이언트가 해당 기기에 접속해 원하는 데이터를 가져오는 프로세스를 짜야했다.

 

중간까지는 되다가 끊기는 현상이 반복되었다. 솔직히 왜 인지 모르겠다.

 

아예 기기접속이 안되는거면 안되야되는데 접속은 되는데 프로세스가 죽는것도 아니고 중간까지 가다가 수행이 되었다고 나오는데 결과가 나오지 않았다.

 

생각해볼 수 있는건 2가지 였다.

 

1. 권한문제

 

내가 실행하려는 테스크가 실행할 수 있는 권한이 아니어서 중간에 return되고 프로세스가 수행된 것 처럼 마무리 된것이다.

 

근데 이거는 아닌거로 예상이 되었다. 

 

이유는 권한문제라면 특정권한이 필요한 명령은 실행되지 말았어야하기 때문이다.

 

 

2. 프로세스 충돌

 

이미 미러링되고 있어 자원을 차지하고 있다고 가정하고 특정 요청이나 커맨드를 입력하려고하면 외부에서 들어오는 요청을 받아들여주지 않는것이다.

 

다음과 같은 생각으로 접근했는데 얼추 맞았던거 같다.

 

지금도 이게 정확히 일치하는지는 모르겠지만 알아낸 사실을 다음과 같다.

 

운영체제에서 지원하는 특정 커맨드(명령어)중 독점적으로 사용되는 커맨드가 존재한다.

 

예를 들어 Ubuntu 버전 ec2를 사용했을 때 여러 명이 ssh로 접속해서 ls 란 커맨드를 입력했을 때 당연하게 지원하지만 

 

그렇지 않고 튕겨내는 커맨드가 존재하는것. 

 

그 커맨드가 어떤 것 인지는 모르겠지만 해당 엔진에서 계속 폴링 방식으로 요청하는 커맨드를 내가 프로세스로서 실행한 것 같다.

 

그래서 나의 요청이 거부되고 중간에 실행이 끊긴걸로 보인다.

 

일단 프로세스간 통신 방법중에 가장 무식한 방법인 파일로 받아서 처리하는 방법을 선택했지만 이거를 이제 어떻게 매꿀지 고민이다......

 

 

퇴근 후 공부

 







A와 B의 데이터의 송수신이 있다고 하면 B가 다른 여러 작업을 하다가 데이터가 온 것에 확신이 찼을 때 데이터를 가져와야한다. 그러려면 데이터를 저장할 버퍼가 필요할 수 밖에 없다.

즉 A가 B의 버퍼에 데이터를 채우고 B의 버퍼가 차있으면 B가 그것을 읽는 형식이다.


입출력 버퍼는 TCP 소켓 각각에 대해 별도로 존재한다.
입출력 버퍼는 소켓 생성시 자동으로 생성된다.
소켓을 닫아도 출력버퍼에 남아있는 데이터는 계속해서 전송이 이루어진다.
소켓을 닫으면 입력버퍼에 남아있는 데이터는 소멸되어버린다.

이와 같은 버퍼가 존재하기 때문에 데이터의 슬라이딩 윈도우 프로토콜의 적용이 가능하고, 이로 인해서 버퍼가 차고 넘치는 상황은 발생하지 않는다.

예를 들어보자
B 클라이언트와 A 클라이언트가 존재한다고 가정하면

B클라이언트는 write함수를 호출해서 data를 보낸다. 근데 이는 상대방의 입력버퍼에 무조건 채우는건 아니다 -> 상대방의 상태에 따라서 보내야한다.

A 클라이언트 또한 read한다고 바로 읽는것이 아니다. 

write는 나의 버퍼에 데이터를 가져다 놓을테니 -> 니가 관리하는 TCP 프로토콜을 근거로해서 상대방에게 데이터를 보내라

이후에 OS , 즉 운영체제가 TCP 프로토콜에 일부인 슬라이딩 윈도우 프로토콜을 근거로 상대방이 허락해주기를 기다린다.
그러면 다른 한 클라이언트에서는 어느정도 보내도 된다고 허락이 떨어지면 버퍼에 해당 크기에 맞는 데이터를 보낸다.

B 클라이언트가 이 순서에 맞춰서 데이터를 50바이트를 보냈다고 하고 A 클라이언트가 20바이트 정도를 읽었다고 이후에 70바이트 까지는 보낼 수있다고 또 메시지를 전달한다.

그러면 B클라이언트는 보낼수 있는 최대 값인 70바이트란 정보가 저장되고 최대 70바이트까지 보낸다.

버퍼를 읽고 채우고 하는 방식이 창문을 미는 방식과 비슷하다해서 슬라이딩 윈도우 라고 한다.

TCP 프로토콜이 구현 가능한 이유는 입출력 버퍼가 존재해서 이다.

 

TCP의 내부동작 원리 1 : 상대 소켓과의 연결

 

SYN 는 번호를 알려주는것

SYN을 보낸다는것은 보내는 데이터의 번호를 새기는것이다.

예를 들어 "내가 지금 보내는 패킷에 1000 이라는 번호를 부여하니 잘 받았다면 다음에는 1001번 패킷을 전달하라고 내게 말해달라." 라는 식의 요청이다.

SYN + ACK는 

이후 수신을 받은 클라이언트는 잘받았으니 1001을 보내고 그 다음 SYN을 보낸다. 내가 지금 보내는 이 패킷에 2000이라는 번호를 부여하니 잘받았다면 2001 번 패킷을 전달하라고 말해달라 라는 것이다.

마지막에 보내는 ACK는

좀 전에 전송한 SEQ가 1000인 패킷은 잘 받았으니 다음 번에 SEQ가 1001인 패킷을 전송하기를 바란다. 너 또한 잘받았으니 1001번을 메시지를 사용해서 너 또한 2001번을 사용해서 보내면 된다.라고 말하는 것


이것이 3 handshake이다.


TCP의 내부동작 원리2 : 상대 소켓과의 데이터 송수신

송수신의 원리는 다음과 같다.

SEQ 1200을 보내고 100 byte Data를 보낸다고 했을때 다음 상대 클라이언트는 ACK로 1301을 보낸다. 

그 후 SEQ는 1301로 100바이트를 보내면 ACK로 1402가 온다.

ACK 번호 = SEQ 번호 + 전송된 바이트 크기 + 1

이처럼 ACK의 값을 전송된 바이트 크기 만큼 증가시키는 이유는 패킷의 전송유무 뿐만 아니라, 데이터의 손실유무까지 확인하기 위함이다.

이렇게 보내야 보내는 사람도 다음 SEQ번호나 ACK번호를 유추가 가능하고, 

돌아오는 ACK와 비교하여 손실유무 판단이 가능하다.

 


만약에 위에 그림처럼 SEQ를 보냈는데 내가 보낸 SEQ에 대해 일정 시간동안 ACK가 오지 않는다면 다시 SEQ를 보낸다.

이 것은 SEQ전송 시 타이머가 작동하여 확인한다.

 

TCP의 내부동작 원리3 : 상대 소켓과의 연결종료


예를들어 소켓 A가 다른 소켓 B에게 SEQ 5001 번호를 매겨 FIN이라는 메시지를 보낸다.

그러면 B는 SEQ 7500번호와 ACK 5001로 요청 확인을 시켜주고 잠시 기다리라고 말한다.

B가 다 정리하고 끊을 준비가 되면 SEQ 7501 번호로 5001의 ACK와 FIN 메시지를 보낸다.

그러면 마지막에 확인 하는 ACK을 보내고 SEQ 5001로 마지막 7502 ACK를 보내고 끝난다.

'일상,취미' 카테고리의 다른 글

다시 시작하는 TIL 18일차  (0) 2024.07.02
다시 시작하는 TIL 17일차  (0) 2024.06.29
다시 시작하는 TIL 15일차  (0) 2024.06.27
다시 시작하는 TIL 14일차  (0) 2024.06.26
다시 시작하는 TIL 13일차  (0) 2024.06.24