3-way handshake란 TCP/IP 에서 호스트와 서버가 Connection 을 맺을때 수행되는 전송제어 프로토콜(Transmission Control Protocol) 이다. (SYN-SYN-ACK 라고도 한다.)
순서는 다음과 같다. Host A가 server, B는 client라고 가정하자.
1. HOST A는 B에게 TCP SYNchronize packet을 보낸다 2. B는 A에게 SYN 패킷을 받는다. 이후 SYNchronize-ACKnowledgement 패킷을 보낸다. 3. A는 B의 SYN-ACK를 수신후 다시 A에게 ACKnowledge 패킷을 보낸다. 4. B가 ACK를 수신하고 TCP 소켓이 ESTABLISHED 된다.
위 그림에서 SYN 패킷을 보낼때, M과 N이 보이는데 이는 Sequence Number 라 한다, 여기에 랜덤한 숫자가 담겨진다. 초기 Sequence Number를 ISN이라 하는데, 이는 0이 아닌 랜덤한 숫자가 보내진다.
단순히 응답을 주고받는데 2-way Handshake면 충분해보이지 않는가? 왜 3-way 일까?
TCP/IP 통신은 양방향성 connection 이다. A host가 B host에게 존재를 알리고 패킷을 받을수있다는 것을 증명하듯이, B host도 패킷을 보낼수 있다는 신호를 보내야한다. 이는 2-way handshaked에서는 성립될 수 없다.
4-way handshake
TCP연결이 해제 될때는 FIN 패킷, ACK 패킷을 각각 한번 씩 주고 받으면서 연결을 종료 하게 된다. 이를 4 way handshake라 한다
ESTABLISHED 된 소켓을사용하는 A Host와 B Host가 있다. A HOST는 이제 연결을 종료하려고한다. 1) A host는 B호스트에게 FIN Flag 패킷을 보내고 socket의 상태가 FIN_WAIT_1 이 된다. 2) FIN 을 수신한 B는 ACK를 전송하고 socket의 상태가 CLOSE_WAIT로 변경한다. 3) ACK를 수신한 A는 B가 잘받았다고 판단하고 FIN_WAIT_2 의 상태로 소켓을 변경한다. 4) B는 A에게 FIN을 전송하고 소켓을 LAST_ACK로 변경한다. 5) FIN을 수신한 A는 B에게 ACK를 전송한뒤 상태를 TIME_WAIT 상태로 변경한다. 6) B는 ACK를 수신하고 소켓을 CLOSED 한다.
CLOSE_WAIT 와 TIME_WAIT 상태란 무엇일까?
TIME_WAIT 상태로 대기하는(60s) 이유는, 세션 종료후, 혹시나 네트워크에 아직 라이브 패킷이 존재할수도 있기때문이다.
최근 git cli를 사용하려고 노력중이다보니, Source tree를 사용하지 않고 직접 cmd를 치다보면 merge를 해야할지 rebase를 해야할지, 헷갈리때가 있다. 또한 옵션에 대해서도 잘 모르고 써었는데 한번 정리해보자 한다.
Solution
기본적으로 git pull = git fetch + git merge 이다.
그러면 어느때 git merge를 쓰고 어느때 git rebase를 써야할까?
Merge
위의 경우가 통상적인 merge 방법이나 이렇게 되면 작업 history가 가시적일 순 있어도 branch가 많아지면 많아질수록 알아보기가 어려워진다. 사람들은 이러한 이유로 rebase를 쓴다.
rebase
master 브랜치를 Fast-forward시킨다 ('앞으로 진행한' 커밋인 master 브랜치 포인터는 최신 커밋으로 이동한다. 이런 Merge 방식을 'Fast forward'라고 부른다.)
위와같이 c3` 커밋메세지 기반으로 history가 정리됨을 알수있다.
tip) git rebase [basebranch] [topicbranch] 처럼 인자를 준다면 일일히 checkout 하지 않고 rebase할 수있다.
위 그림같은 경우는 $ git rebase master experiment
Merge
Rebase
특징
- branch의 최종 결과만을 가지고 합병
- 지정한 브랜치를 베이스로 기준 삼아 합병
- 중복수정된 로그가 남지않는다.
- 브랜치의 변경사항을 순서대로 다른 브랜치에 적용하면서 합병
장점
- 이해하고 사용하기 쉬움
- 브랜치 컨텍스트 유지
- history가 단순해짐
- branch가 많을때 커밋을합치는 직관적인방법
단점
- 히스토리가 난잡
- 커밋 순서대로 rebase를 하는데, 각 커밋마다 충돌해소를 순서대로 해주어야하여 복잡함
추가유용 명령어 - FILE 되돌리기 및 삭제편
git checkout [-- 파일명] 아직 스테이징이나 커밋을 하지 않은 파일의 변경내용을 취소하고 이전 커밋상태로 돌린다. svn에서 revert와 동일하다 (그냥 git checkout branch를 할경우 현재 활성화된 브랜치를 바꾸는 명령어이다)
git checkout -- . wd에 수정된내용 모두 되돌림
git diff [--cached] 스테이징영역과 현재 작업트리의 차이점을 뵤어준다. --cached 옵션을 추가하면 스테이징영역과 저장소의 차이점을 볼 수 있다. git diff HEAD를 입력하면 저장소, 스테이징영역, 작업트리의 차이점을 모두 볼 수 있다. 파라미터로 log와 동일하게 범위를 지정할 수 있으며 --stat를 추가하면 변경사항에 대한 통계를 볼 수 있습니다. git diff --ours 머지이전과 머지이후 결과비교
git reset — hard HEAD^ commit한 이전 코드 취소하기
git merge --abort 머지 취소하기(커밋이나 stash 하지않는 존재시 못함)
git config — global user.name “user_name ” git 계정Name 변경하기
git config — global user.email “user_email” git 계정Mail변경하기
git reset — hard HEAD && git pull git 코드 강제로 모두 받아오기
git reset --hard HEAD머지하기이전상태로 모두되돌림
git reset --[hard] [mixed] [soft]
--hard: reset하기 전까지 했던 staging area, working directory의 작업까지 모두 reset! (모든 게 잘못됐어! 나 돌아갈래~ 꽃피던 때부터 정갈하게 다시 해보자!) --mixed(default): staging area은 reset, reset하기 전까지 했던 working directory의 작업은 남겨둠. (현재 작업물은 지우긴 싫고, 이전 버전으로 돌아가서 add할지 말지 결정해야 할 때) --soft: reset하기 전까지 했던 staging area, working directory의 작업은 남겨둠. (reset한 버전과 현재까지의 작업을 합쳐 새로운 버전 만들 때) git reset --hard 커밋된 파일빼고 모두삭제 git clean -df 커밋,stage 되지 않은 파일 폴더 모두삭제 [untrack 중인] (매우 유용)