Quantcast
Channel: 우분투 한국 커뮤니티
Viewing all articles
Browse latest Browse all 4577

Re: tcpdump 에서 Flags[S] 만 뜨는 현상

$
0
0
Author: happyman
Forum: 서버/네트워크 게시판
Date: 2014-08-14

저는 사실 php에서 socket programming을 해본 경험은 없구요. php에 socket이 있는 줄도 처음 알았네요. ㅎㅎㅎ

예전에 제가 개발했던 C application에 internet support가 필요해서 잠시 해본 경험이 전부이긴 합니다만... client 쪽에 문제가 있는 경우는 드물죠. Client야 사용하다가 전원 꺼버리고 가는 경우도 있고, 참 다양하게 쓰니까요. 첫번째 시도는 된다고 하셨으니, client가 죄를 저질렀을 가능성은 적죠. 아무튼 제가 지금 그 code를 읽어서 분석할 수는 없구요. 그냥 개념적인 문제로 그리고 C언어 system call을 기준으로 말씀드릴께요.

문제는 server program이죠. 예를 들어 application의 규칙(protocol)에 따라 메세지를 주고 받는다고 가정하죠. 근데 이유가 뭐가 되었건 client가 중간에 그대로 나가버리면 (예: 전원 OFF), 그래도 server는 동작해야 합니다. server는 그 client에만 service할 수 없으니까요. 장비 A만 있다면, 모르지만, 다른 장비의 connect request를 들어야 하잖아요? 장비 A에게만 서비스를 한다고 하더라도 2nd service request를 들어야 할 것이구요. 근데, 서버는 client가 나가버린 그 상황을 모르니 마냥 기다리게 될 수도 있고, 다음 service를 위하여 끊어 버리기도 난감하고 그렇다는 것이죠. 제가 의심하는 것은 이런 상황이었습니다. 기존 package들이야 이런 상황에 대비하는 program을 하지만, 학생 project에서는 제대로 된 상황에만 적용되는 program을 하는 것은 흔한 일일 수 있으니까요. 기존 package인지 학생 project인지 물어본 이유가 이것입니다.

그런 이유로, server 쪽은 일단 connection request가 오면, 즉, system call accept() 가 떨어지면, 그다음부터는 fork() call을 이용하여 새로운 child process를 만들어서 그 child process가 나머지 통신 과정을 담당하게 하죠. 그렇게 하면, child process가 첫번째 client와의 통신 과정을 담당하고, parent process는 새로운 sevice를 위하여 port를 듣는 일을 하게 되는 것이죠. 이렇게 하면, 처음 장비와의 통신에 문제가 생겨도 다른 새로운 장비에 서비스를 계속할 수 있다는 것입니다. 문제가 생긴 장비의 경우, timer 같은 것을 이용하여 zombie processs가 생기는 것은 막을 수 있을 것이고요. 요즘은 process를 쓰지 않고 thread를 이용하는 경우도 있다더군요. 저는 thread로 해보진 않아서 잘 모르지만, 장단점이 있겠죠. Client가 protocol를 지킨다는 보장도 없고 Program에 minor bug가 없으라는 법도 없으니, 그런 문제에 대처하기 위하여, 대부분의 서버가 이런 방식으로 처리하는 것으로 저는 알고 있습니다.

rura6502님의 경우에도 그런 문제를 의심했습니다. 첫번째 접속에서는 잘되었겠죠. 그런데, 첫번째 접속에서 protocol에 따라 통신을 마치고 socket을 제대로 닫아주지 않으면, 일종의 dead-lock에 걸릴 수 있다는 것이죠. 그럼 두번째 접속에서 server는 데이터를 기다리고 있는데, client는 connectiom request를 하고 있는 상황에 처할 수 있잖아요? child process에서 담당하도록 떼어 버리면, parent process에서 계속 들으면 되니 문제가 없다는 것이죠.

Server가 통신을 child process에서 처리하는 경우에도 client program에 문제가 있다면 문제가 있을 수 있는데... 사실 가능성은 거의 없는데요. tcp는 server IP/server port/client IP/client port의 4개 묶음으로 연결을 규정합니다. 그런데, Server IP/server port/client IP는 하나의 장비를 가정하면 똑같죠? 그러니, 장비 A의 전원을 끄고, 전원을 다시 켰을 때, 같은 client port를 사용한다면 연결이 동일해지게 됩니다. 따라서, 새로운 연결이 시도되는 것이 아니라 기존의 child process가 이 메세지를 가져갈 수 있다는 것이죠. 전원 OFF 이전의 통신 과정에서 child process가 제대로 끝나지 못했다면 그렇게 될 수 있고, 이 경우, child process는 read() call을 하고 있는데, client는 connect() call을 하는 상황이 될 수도 있다는 생각인 것입니다. 그래서 전원 OFF 이전과 이후 다시 ON했을 때 child port number를 보고 싶었는데 가려 놓으셨더라구요. 근데, 뭐 같은 가능성은 거의 없죠. 제가 알기로는 random number generation에 의하여 child port number가 정해지는 것으로 알고 있으니까요. 그러므로 이 가능성은 없다고 보아도 될 것입니다.

결론적으로, sever가 통신하는 과정이 child process가 담당하게 하는 것이 아니라면 (php code를 제대로 읽지 않아서 모릅니다), 매우 위험합니다. dead-lock에 빠지기 매우 쉽습니다. child process가 담당하게 하는 경우에도 제대로 protocol이 완성된 후, exit하도록 program 하세요. client가 저 혼자 죽어버리는 경우에 대비하여 적절한 timer도 설치하세요.

원인이 이것이 아니라면, 저도 모릅니다. 몇마디 하다보면 바닥이 곧 드러난다고 말씀드렸잖아요. 아무튼 현상을 보면, dead-lock 혹은 유사한 현상으로 보입니다.

Viewing all articles
Browse latest Browse all 4577

Latest Images

Trending Articles