2014-07-23
php는 소켓통신시에 보내지는 값이 string타입으로만 보내진다. 애초에 php는 변수의 형을 제대로 따지지 않으니 이럴수 밖에 없을꺼 같기도 한데, 이렇게 되면, c로 만들어져서, 전문에 int형으로 되어 있는 값들을 포함되어 있으면, 해당 전문을 보내주려면 문제가 생겨 버린다.
c의 int타입은 기본적으로 정해진 길이가 있기 때문에, php의 유동적인 변수와는 패킷 형태가 달라지기 때문이다.
하지만, 반대로 어떤 값을 보내던 결국엔 패킷 형태로 가기 때문에, php에서 보내지는 값을 byte단위인거 처럼 속여서 보내면 결국 패킷을 봤을때는 똑같은 값으로 보내지게 할 수 는 있다.

간단한 예를 들어보겠다.
int타입으로 소켓 통신을 할 경우 int형 변수의 값이 1이라고 하였을때, 패킷은
01 00 00 00
위와 같이 나온다.
그럼 php에서 위와 같은 패킷값이 나오게 하려면,
$req = str_replace( "^", chr(1), sprintf( "%'.-4s", "^" ) );
$req = str_replace( ".", chr(0), $req );
위처럼 만들면 된다.

설명을 하자면, 4바이트를 차지하고 왼쪽부터 채워지는 문자를 넣기 위해서 printf함수를 이용하여 "%'.-4s"형식으로 없는 칸에는 "."을 채워 넣는다. 그리고 알다시피 php에서의 소켓통신은 string값으로 전해지기 때문에, 패킷에서의 01값을 표현하기 위해서는 아스키코드값의 01값으로 바꾸어 주어야 한다. 여기가 조금 헷갈릴수 있는 부분인데...
c언어에서는 int형으로 변수를 선언하여 해당 값을 소켓통신으로 전달할때, int형이기 때문에 있는 그대로 1이 들어갈 것이다. 하지만, php는 string 타입만 있기 때문에, 1을 넣어서 보내도 1이 아닌 아스키 코드값의 31이 나온다. 그래서 string타입으로 보내면서도 숫자로 나오게 하기 위하여 chr()함수를 이용하여 값을 집어넣어주는것이다.
chr(1)이라고 해당 숫자에 해당하는 string타입의 문자가 들어가고, 실제 패킷에서는 1이라고 표시되는 것이다.
마지막으로 나머지 자리들은 위 소스에서 보면 알다시피 "."으로 채워 놓았는데, 그것을 전부 실제 0값으로 바꾸어 주고 있다.

아무리봐도 편법이고, 숫자가 복잡해지거나 여러자리에 걸쳐서 들어갈때는 좀더 처리해줄게 많아지겠지만, 이렇게라도 처리하는게 가능하긴 하니, 알아서 잘 응용해 보기 바란다....ㅡ/.ㅡ