메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

PHP로 소켓 프로그래밍 하기

한빛미디어

|

2002-10-04

|

by HANBIT

17,648

저자: 다니엘 솔린(Daniel Solin), 역 한빛리포터 최연기

C로 네트워크 프로그래밍을 배우기 위해 필사적으로 노력하지만, 거친 야수를 길들일 스태미나가 없는가? 실제로 필자도 이와 같은 상황이었다. 사실 C를 배우기까지 많은 시간이 걸렸다. 나 자신의 만족감 뿐 아니라, 네트워크 프로그램을 요구하는 문제에 부딪쳤기 때문이다. 오랜 노력의 밤을 보낸 후, 나는 완전히 괴멸되었다. 그 무렵 나는 내가 가장 좋아하는 프로그래밍 언어인 PHP에 기본적인 소켓 도구가 포함되어있다는 것을 깨달았다. 할렐루야! 난 살았다!

PHP의 근본적인 목적은 웹기반 애플리케이션 개발을 위한 높은 수준의 프로그래밍 언어라는데 있다. 그러나 PHP는 네트워크 프로그래밍과 같이 다른 목적을 위해 사용할 수도 있는 훌륭한 특징이 있다.

소켓 이해하기

안타깝게도 PHP는 소켓이 정말 무엇인지, 어떻게 소켓을 이용해 두 컴퓨터 사이의 통신을 발생시킬 수 있는지와 같은 기본적인 것들을 알려주진 않는다. 그래서 본 기사에서는 이 부분을 파고들 것이다. 정말 이해하기 그렇게 힘든 기사가 아니므로 누구든 쉽게 이해할 수 있다는 희망으로 이 기사를 시작해보겠다.

네트워크가 무엇인지 아는가? 소켓이 무엇인지 아는가? 정말? 소켓은 단지 운영체제의 저수준의 특징을 가진 추상 도구일 뿐이다. 어쨌든, 프로그램들 안에서 소켓을 사용하기 위해서는 깊이 들어갈(깊이 알) 필요가 없다. 단지 소켓이 어떻게 추상적으로 동작하는지와 같은 기본적인 사항에 대해 이해만하고 넘어가면 된다.

이것을 설명하기위해, 필자는 비디오 게임의 프로세스와 비교를 할 것이다. 컴퓨터 게임은 실제 세계와 아주 닮았지만 게임 안에서 모든 컴퓨터 네트워크는 작은 사람들에 의해 구성된다. 여러분은 이들 작은 사람이 원하는 대로 똑같이 동작하게 할 수 있지만 여기에도 현실 세계와 다른점이 있다. 이 사람에게는 지능이 없다. 어떤 잘못이 일어난다고 하더라도 주어진 명령대로만 실행하기 때문이다.


[그림 1] 작은 사람들로 네트워크 컨트롤하기

여기에서 과연 게임의 목적이 무엇인지와 같은 게임에 대한 설명이 필요하다고 생각한다. 일단 여러분은 네트워크 연결을 통해 이동할 수 있고 데이터가 도착하기를 기다리는 “Computer I” 안에 있는 사람을 만들어야 한다. 데이터가 도착하면 데이터가 들어올 수 있게 해치를 열 준비가 다 된 것이다. 이 데이터가 해치를 통해 들어오면 누군가가 컴퓨터 안의 정확한 목적지로 데이터를 인도해야 한다. 여기에서 게임 속 사람에게 해치를 여는 일을 요청한다면, 추가적인 데이터가 들어오려 할 때 해치가 확실히 열려진다고 할 수 있겠는가?

이 문제를 해결하기위한 정말 간단한 해결책이 있다. 다른 사람에게 머신 안의 도착지에 해치를 통해 무엇이 도착했는지 물어보면 된다. 이 일을 하는 동안 여러분은 처음의 사람이 해치를 (여는) 작업에 집중하게 놓아두면 된다.

그러나 그 일을 아직 완전하게 한 것은 아니다. 무엇인가가 나가기를 원할 때 해치로 가서 해치가 열렸다고 확인할 수 있는 다른 사람을 Computer II 안에 만들어야 한다. 이제 첫 게임을 시작할 것이다. 그러면 그 게임이 어떻게 동작하는지 볼 수 있다. 몇몇 버튼을 누르고, 조이스틱을 움직여 출발할 것이다. 여길 보시길… 쨘~ [그림 2]를 보아라.


[그림 2] 모든 것이 자기 자리에 잘 있다.

그러나 이게 무엇인가? 3번째 사람은 어디 있는가? 침착하자. 자기 자리에 잘 있을 것이다. 그러나 무언가 도착할 때까지 그 사람을 그곳에 세워두면 그가 가진 훌륭한 능력을 낭비하는 것이라는 생각이 들지 않는가? 무슨 일이든지 필요한 일을 시키고 그가 진짜 해야 할 일이 생기면 그때 그를 부르는 것이 좋지 않을까?

나의 조정 하에 좀 더 누르고, 닫고, 친 후에 나는 약간의 데이터가 있어야 한다고 Computer II 에게 말한 후, 해치를 열고 데이터를 내보낼 수 있게 Computer II 안의 사람을 다른 곳으로 옮겼다. [그림 3]에서 데이터는 길 위에 있다.


[그림 3] 길 위에 있는 데이터

그림에서 보는 것처럼, 데이터 덩어리는 지금 Computer II의 해치를 통과해 지나가고, “Computer I”로 가는 길 위에 있다. (어떻게 이 큰 덩어리가 작은 해치를 통해 지나 갔는지 궁금해 하지마라!) 그냥 이것 저것 누르고, 만지는 조정으로 훌륭하게 잘 도착했으니까. 이제 여러분은 데이터 덩어리를 가지게 되었다.


[그림 4] 데이터 도착

여기서, 나는 Computer II에서 데이터를 받기 위해 조정했다. 네트워크 연결을 통해 데이터를 보낸 다음 Computer I로 갔다. 그리고 이 데이터를 다루기 위해 Computer I 안에 있는 두 번째 사람을 불렀다. 보이는 것처럼, 적당한 자리에서 그 데이터를 얻었다. 이쯤이면 만족할만하다고 할 수 있지 않겠는가!

PHP에서 소켓 프로그래밍하기

게임 안에서, 작은 사람은 실제적인 네트워크 소켓이고, 조정은 내가 가장 좋아하는 프로그래밍 언어인 PHP를 재연했다고 보면 된다.

PHP의 네트워크 소켓은 C가 구현하는 것처럼 최고급 형태는 포함하지 않았지만, 모든 네트워크 응용 프로그램의 95%에 육박하는 것으로 그렇게 나쁜 것은 아니다. 또한, PHP 같은 사용하기 쉬운 언어를 사용하여 진짜 네트워크 응용 프로그램을 작성할 수 있을 것이다. 이제 간단한 TCP 서버를 보자. 여기를 클릭해보자.

이 프로그램과 비슷하게 만들어진 게임(위에서 예를 들어 설명한 게임)은 이제 완전히 이해되었다. 잠시동안 이에 대해 논의 해보자. 먼저, 8번 라인에서 시간 제한 없이 연결을 기다릴 수 있는 PHP를 부르기 위해 set_time_limit(0)를 사용한다. 이것은 해치를 기다리기 위해 사람을 부르는 것과 같다. (또는 적어도 우리는 솔직히 그곳으로부터 그들이 떠날 때까지 부른다.)

11에서 15 라인은 새로운 소켓을 생성하는 라인이다. global socket으로 알려진 이것은 들어오는 연결(incoming connections)을 조사한다. (이런 점에서, 이 소켓은 Computer I 의 해치를 조절하는 사람에 해당한다고 볼 수 있다.) 이를 위해 우리는 모두 3개의 인자를 가지는 socket() 함수를 사용한다. 필자는 이 파라미터들을 설명하려고 노력하지 않았기 때문에 이 기사를 네트워크 프로그래밍을 소개하는 기사로 작성하였다. 만약 우리가 여기서 사용하려는 것 이상의 인자에 대해 설명해줄 것을 원한다면 이미 자신이 네트워크 프로그래밍에 깊이 빠져있다고 봐도 무관할 것이다. 그러나 (UDP에 반대하여) TCP 프로토콜을 이용하기를 원할 경우 선언해야 할 두 번째 인자인 SOCK_STREAM 정도는 알아두는게 좋을 것이다.

18에서 22라인까지, 새로 만들어진 소켓은 IP 주소와 포트에 묶여진다. 우리가 머신에서 이 프로그램을 실행하려면, IP 주소로 127.0.0.1을 사용한다. 우리가 사용하는 포트인 10000은 임의로 뽑힌 것이다. 여러분은 사용 중이지 않은 1024부터 65535사이에 있는 포트는 어떠한 것이라도 사용할 수 있다. 마찬가지로 이것은 네트워크 연결(해치)을 조절하고, 특정 네트워크 데이터를 책임질 수 있는 한 명의 작은 사람을 얘기한다. 만약 포트 10000번으로 도착하는 패킷이 있다면, 우리의 작은 사람은 자신이 이것을 조심스럽게 다루어야 한다는 사실을 안다. (불가사의 하겠지만, 이 작은 사람은 실제로 데이터 패킷에게 말을 할 수 있는 것이다!)

포트의 소개와 함께, 같은 해치에서 무언가 도착하기를 기다리는 많은 사람들이 있다는 것도 이미 이해했다. 데이터를 받는 포트는 특정한 한 (작은) 사람이 들어온 데이터를 돌보아야 할지 아닐지를 결정한다. 그러므로 우리의 (작은) 사람은 포트 10000번으로 가는 데이터에 대해서만 신경을 쓸 것이다.

지금까지 우리는 무엇을 해야 하는지 잘 아는 사람을 데리고만 있었지 아직 그를 보내는 명령은 하지 않았다. 그 사람을 소파에서 불러서 해치로 가게 만드는 과정은 28에서 31라인을 통해 완료되었다. 34~38라인에서, 우리는 그가 거기에 머물면서 필요한 경우 해치를 열도록 조치를 취해 놓았다. 프로그램이 실행되는 동안, accept_connect() 함수는 연결이 도착할 때까지 기다릴 것이다. 그러므로, 프로그램은 우리가 잠시 후 텔넷을 사용하여 접속할 때까지 여기에서 실행을 멈추어 있을 것이다. 또한 연결이 발견되면, accept_connect()은 연결된 쪽과 통신을 다루는 $msgsock 라는 또 다른 소켓을 만든다는 것에 유의하자. 이것은 [그림 4]에서 본 3번째 사람이다. (그는 들어온 데이터를 다루었다.)

41~46라인에서, write() 함수를 사용해서 환영 메시지를 보낸다. $sock는 자신의 해치문제로 바쁘기 때문에 이 작업은 $msgsock에 의해 이루어진다는 것에 유의해야 한다. 이번 단계에서 accept_connect() 함수는 이미 연결을 발견했기 때문에 스크립트 실행은 이곳까지 왔다. 이와 마찬가지로 그 사람은 무언가 들어오는 것을 보고, 해치를 열고, 패킷이 어디로 가는지 물어보았다. 패킷이 “포트 10000”이라고 대답하면, 그는 패킷을 들어오게 해서 자신의 도우미인 $msgsock에게 보낸다.

49~54라인에서는 먼가 꽤 재미있는 일이 일어났다. 여기에서 우리는 해치에 가서 대기하고 있는 두 번째 사람인 $msgsock를 부른다. 이것은 $sock가 그는 돌보는 것이 필요한 무언가가 들어왔을 때 그가 준비되었다고 확신하게 한다. 프로그램이 실행되는 동안, 연결로부터 데이터를 읽기 위해 read()를 사용하지만 우리를 위해 다른 쪽에서 보내진 어떤 데이터도 받을 수 있다. accept_connect()처럼 read() 명령도 무언가 일어날 때까지 기다릴 것이다. 데이터가 포트 10000으로 도착하면 두 번째 사람인 $mssock는 데이터를 가지고, $buf 값으로 가는 길을 보여줄 것이다. 따라서 지금 $buf에 그 데이터를 가지고 있다. 그 결과 57~61라인에서 멋진 응답을 보낼 수 있다. 다시 말해 $msgsock는 이것을 돌보고, $sock는 해치를 열고 닫기만 할 것이다.

이 스크립트에서 우리가 할 마지막 일은 $sock$msgsock 두 사람에게 집으로 가서 쉬라고 명령하는 것이다. (64에서 67라인) 좀 더 기술적으로 말한다면 두 소켓과 네트워크 연결을 닫는 것을 의미한다.

TCP 서버를 테스트하자

이제 테스트를 할 시간이다. 테스트는 항상 가장 재미있는 부분이다. 그러나 스크립트를 실행하기 전에 일단 이것이 정확한 퍼미션을 가지고 있는지부터 확인하자.
chmod 755 lst01.php
또한 스크립트의 첫 라인에서 PHP 바이너리(#!/usr/local/bin/php -q)를 지정하는지 확인하는 것도 잊지 말자. 그런 다음, 서버를 시작하자.
./lst01.php
(만약 socket() 함수가 정의되지 않았다는 에러가 나온다면 당시의 PHP 소스 디렉토리 안으로 가서 ./configure --enable-sockets를 실행하고, make && make install을 실행해서 PHP 바이너리를 다시 컴파일하고 설치해야 한다.)

이제 다른 터미널을 열고, 다음 명령어를 실행하자.
telnet 0 10000
이것은 여러분이 포트 10000번을 사용하여 머신과 텔넷 연결을 하고싶다는 것을 의미한다. 만약 모든 것이 정상이라면 아래와 같은 출력을 얻을 수 있을 것이다.
Trying 0.0.0.0...
Connected to 0.
Escape character is "^]".
Welcome to my TCP server!
이제 무언가 쓰고 엔터를 눌러보자.
Hello
You said: Hello
Connection closed by foreign host.
기쁘지 않은가? 그렇게 고급은 아니지만, 실제 네트워크 연결을 만들고 이를 통해 약간의 정보를 교환했다.

요약

본 기사에서 여러분은 네트워크 소켓을 이용해 어떻게 두 컴퓨터 사이에 데이터를 교환하는지 배웠다. 이를 이해해서 잘 활용하기를 바란다. 성공한 프로그래머가 되는 열쇠는 함수 호출이 정확히 어떤 일을 하는지 이해하는 것이다. 이를 이해할 수 있을 때에야 여러분은 진정 자신만의 프로그램을 조절할 수 있다고 말할 수 있을 것이다.

기억하라! 네트워크 프로그래밍은 네트워크 연결을 통해 데이터를 보내고 받는 모든 것을 말하는 것이다. 우리는 오늘 그 가지를 해 보았다. 하찮다고 생각될 수도 있겠지만 오늘 여러분은 대단한 것을 해본 것이다.
다니엘 솔린(Daniel Solin)은 자유기고가이자 GUI 프로그래밍을 전문으로하는 리눅스 컨설턴트이다. SAMS에서 출간된 『Teach Yourself Qt Programming in 24 hours』는 2000년 5월에 출간된 그의 첫 저서이다.
TAG :
댓글 입력
자료실

최근 본 상품0