例如,需要发送以下数据
struct header
{
int type;
// 消息类型
int length;
// 消息长度
}
struct MSG_Q2R2DB_PAYRESULT
{
int serialno;
int openid;
char payitem[512];
int billno;
int zoneid;
int providetype;
int coins;
}
调用的方法,另外需require两个php文件,一个是字节编码类,另外一个socket封装类,其实主要看字节编码类就可以了!
1 public function index() {
2 $socketAddr = "127.0.0.1";
3 $socketPort = "10000";
4 try {
5
6 $selfPath = dirname ( __FILE__ );
7 require ($selfPath . "/../Tool/Bytes.php");
8 $bytes = new Bytes ();
9
10 $payitem = "sdfasdfasdfsdfsdfsdfsdfsdfsdf";
11 $serialno = 1;
12 $zoneid = 22;
13 $openid = "CFF47C448D4AA2069361567B6F8299C2";
14
15 $billno = 1;
16 $providetype = 1;
17 $coins = 1;
18
19 $headType = 10001;
20 $headLength = 56 + intval(strlen($payitem ));
21
22 $headType = $bytes->integerToBytes ( intval ( $headType ) );
23 $headLength = $bytes->integerToBytes ( intval ( $headLength ) );
24 $serialno = $bytes->integerToBytes ( intval ( $serialno ) );
25 $zoneid = $bytes->integerToBytes ( intval ( $zoneid ) );
26 $openid = $bytes->getBytes( $openid );
27 $payitem_len = $bytes->integerToBytes ( intval ( strlen($payitem) ) );
28 $payitem = $bytes->getBytes($payitem);
29 $billno = $bytes->integerToBytes ( intval ( $billno ) );
30 $providetype = $bytes->integerToBytes ( intval ( $providetype ) );
31 $coins = $bytes->integerToBytes ( intval ( $coins ) );
32
33 $return_betys = array_merge ($headType , $headLength , $serialno , $zoneid , $openid,
$payitem_len ,$payitem,$billno,$providetype,$coins);
34
35 $msg = $bytes->toStr ($return_betys);
36 $strLen = strlen($msg);
37
38 $packet = pack("a{$strLen}", $msg);
39 $pckLen = strlen($packet);
40
41 $socket = Socket::singleton ();
42 $socket->connect ( $socketAddr, $socketPort ); //连服务器
43 $sockResult = $socket->sendRequest ( $packet); // 将包发送给服务器
44
45 sleep ( 3 );
46 $socket->disconnect (); //关闭链接
47
48 } catch ( Exception $e ) {
49 var_dump($e);
50 $this->log_error("pay order send to server".$e->getMessage());
51 }
52 }
Bytes.php 字节编码类
<?php
/**
* byte数组与字符串转化类
* @author
* Created on 2011-7-15
*/
class Bytes {
/**
* 转换一个String字符串为byte数组
* @param $str 需要转换的字符串
* @param $bytes 目标byte数组
* @author Zikie
*/
public static function getBytes($str) {
$len = strlen($str);
$bytes = array();
for($i=0;$i<$len;$i++) {
if(ord($str[$i]) >= 128){
$byte = ord($str[$i]) - 256;
}else{
$byte = ord($str[$i]);
}
$bytes[] = $byte ;
}
return $bytes;
}
/**
* 将字节数组转化为String类型的数据
* @param $bytes 字节数组
* @param $str 目标字符串
* @return 一个String类型的数据
*/
public static function toStr($bytes) {
$str = '';
foreach($bytes as $ch) {
$str .= chr($ch);
}
return $str;
}
/**
* 转换一个int为byte数组
* @param $byt 目标byte数组
* @param $val 需要转换的字符串
* @author Zikie
*/
public static function integerToBytes($val) {
$byt = array();
$byt[0] = ($val & 0xff);
$byt[1] = ($val >> 8 & 0xff);
$byt[2] = ($val >> 16 & 0xff);
$byt[3] = ($val >> 24 & 0xff);
return $byt;
}
/**
* 从字节数组中指定的位置读取一个Integer类型的数据
* @param $bytes 字节数组
* @param $position 指定的开始位置
* @return 一个Integer类型的数据
*/
public static function bytesToInteger($bytes, $position) {
$val = 0;
$val = $bytes[$position + 3] & 0xff;
$val <<= 8;
$val |= $bytes[$position + 2] & 0xff;
$val <<= 8;
$val |= $bytes[$position + 1] & 0xff;
$val <<= 8;
$val |= $bytes[$position] & 0xff;
return $val;
}
/**
* 转换一个shor字符串为byte数组
* @param $byt 目标byte数组
* @param $val 需要转换的字符串
* @author Zikie
*/
public static function shortToBytes($val) {
$byt = array();
$byt[0] = ($val & 0xff);
$byt[1] = ($val >> 8 & 0xff);
return $byt;
}
/**
* 从字节数组中指定的位置读取一个Short类型的数据。
* @param $bytes 字节数组
* @param $position 指定的开始位置
* @return 一个Short类型的数据
*/
public static function bytesToShort($bytes, $position) {
$val = 0;
$val = $bytes[$position + 1] & 0xFF;
$val = $val << 8;
$val |= $bytes[$position] & 0xFF;
return $val;
}
}
?>
socket.class.php socket赋值类
1 <?php
2 define("CONNECTED", true);
3 define("DISCONNECTED", false);
4
5 /**
6 * Socket class
7 *
8 *
9 * @author Seven
10 */
11 Class Socket
12 {
13 private static $instance;
14
15 private $connection = null;
16
17 private $connectionState = DISCONNECTED;
18
19 private $defaultHost = "127.0.0.1";
20
21 private $defaultPort = 80;
22
23 private $defaultTimeout = 10;
24
25 public $debug = false;
26
27 function __construct()
28 {
29
30 }
31 /**
32 * Singleton pattern. Returns the same instance to all callers
33 *
34 * @return Socket
35 */
36 public static function singleton()
37 {
38 if (self::$instance == null || ! self::$instance instanceof Socket)
39 {
40 self::$instance = new Socket();
41
42 }
43 return self::$instance;
44 }
45 /**
46 * Connects to the socket with the given address and port
47 *
48 * @return void
49 */
50 public function connect($serverHost=false, $serverPort=false, $timeOut=false)
51 {
52 if($serverHost == false)
53 {
54 $serverHost = $this->defaultHost;
55 }
56
57 if($serverPort == false)
58 {
59 $serverPort = $this->defaultPort;
60 }
61 $this->defaultHost = $serverHost;
62 $this->defaultPort = $serverPort;
63
64 if($timeOut == false)
65 {
66 $timeOut = $this->defaultTimeout;
67 }
68 $this->connection = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
69
70 if(socket_connect($this->connection,$serverHost,$serverPort) == false)
71 {
72 $errorString = socket_strerror(socket_last_error($this->connection));
73 $this->_throwError("Connecting to {$serverHost}:{$serverPort} failed.<br>Reason:
{$errorString}");
74 }else{
75 $this->_throwMsg("Socket connected!");
76 }
77
78 $this->connectionState = CONNECTED;
79 }
80
81 /**
82 * Disconnects from the server
83 *
84 * @return True on succes, false if the connection was already closed
85 */
86 public function disconnect()
87 {
88 if($this->validateConnection())
89 {
90 socket_close($this->connection);
91 $this->connectionState = DISCONNECTED;
92 $this->_throwMsg("Socket disconnected!");
93 return true;
94 }
95 return false;
96 }
97 /**
98 * Sends a command to the server
99 *
100 * @return string Server response
101 */
102 public function sendRequest($command)
103 {
104 if($this->validateConnection())
105 {
106 $result = socket_write($this->connection,$command,strlen($command));
107 return $result;
108 }
109 $this->_throwError("Sending command \"{$command}\" failed.<br>Reason: Not connected");
110 }
111
112
113
114 public function isConn()
115 {
116 return $this->connectionState;
117 }
118
119
120 public function getUnreadBytes()
121 {
122
123 $info = socket_get_status($this->connection);
124 return $info['unread_bytes'];
125
126 }
127
128
129 public function getConnName(&$addr, &$port)
130 {
131 if ($this->validateConnection())
132 {
133 socket_getsockname($this->connection,$addr,$port);
134 }
135 }
136
137
138
139 /**
140 * Gets the server response (not multilined)
141 *
142 * @return string Server response
143 */
144 public function getResponse()
145 {
146 $read_set = array($this->connection);
147
148 while (($events = socket_select($read_set, $write_set = NULL, $exception_set = NULL, 0)) !==
false)
149 {
150 if ($events > 0)
151 {
152 foreach ($read_set as $so)
153 {
154 if (!is_resource($so))
155 {
156 $this->_throwError("Receiving response from server failed.<br>Reason: Not
connected");
157 return false;
158 }elseif ( ( $ret = @socket_read($so,4096,PHP_BINARY_READ) ) == false){
159 $this->_throwError("Receiving response from server failed.<br>Reason: Not
bytes to read");
160 return false;
161 }
162 return $ret;
163 }
164 }
165 }
166
167 return false;
168 }
169 public function waitForResponse()
170 {
171 if($this->validateConnection())
172 {
173 return socket_read($this->connection, 2048);
174 }
175
176 $this->_throwError("Receiving response from server failed.<br>Reason: Not connected");
177 return false;
178 }
179 /**
180 * Validates the connection state
181 *
182 * @return bool
183 */
184 private function validateConnection()
185 {
186 return (is_resource($this->connection) && ($this->connectionState != DISCONNECTED));
187 }
188 /**
189 * Throws an error
190 *
191 * @return void
192 */
193 private function _throwError($errorMessage)
194 {
195 echo "Socket error: " . $errorMessage;
196 }
197 /**
198 * Throws an message
199 *
200 * @return void
201 */
202 private function _throwMsg($msg)
203 {
204 if ($this->debug)
205 {
206 echo "Socket message: " . $msg . "\n\n";
207 }
208 }
209 /**
210 * If there still was a connection alive, disconnect it
211 */
212 public function __destruct()
213 {
214 $this->disconnect();
215 }
216 }
217
218 ?>
PacketBase.class.php 打包类,暂时没用到
1 <?php
2 /**
3 * PacketBase class
4 *
5 * 用以处理与c++服务端交互的sockets 包
6 *
7 * 注意:不支持宽字符
8 *
9 * @author Seven <seven@qoolu.com>
10 *
11 */
12 class PacketBase extends ContentHandler
13 {
14 private $head;
15 private $params;
16 private $opcode;
17 /**************************construct***************************/
18 function __construct()
19 {
20 $num = func_num_args();
21 $args = func_get_args();
22 switch($num){
23 case 0:
24 //do nothing 用来生成对象的
25 break;
26 case 1:
27 $this->__call('__construct1', $args);
28 break;
29 case 2:
30 $this->__call('__construct2', $args);
31 break;
32 default:
33 throw new Exception();
34 }
35 }
36 //无参数
37 public function __construct1($OPCODE)
38 {
39 $this->opcode = $OPCODE;
40 $this->params = 0;
41 }
42 //有参数
43 public function __construct2($OPCODE, $PARAMS)
44 {
45 $this->opcode = $OPCODE;
46 $this->params = $PARAMS;
47 }
48 //析构
49 function __destruct()
50 {
51 unset($this->head);
52 unset($this->buf);
53 }
54
55 //打包
56 public function pack()
57 {
58 $head = $this->MakeHead($this->opcode,$this->params);
59 return $head.$this->buf;
60 }
61 //解包
62 public function unpack($packet,$noHead = false)
63 {
64
65 $this->buf = $packet;
66 if (!$noHead){
67 $recvHead = unpack("S2hd/I2pa",$packet);
68 $SD = $recvHead[hd1];//SD
69 $this->contentlen = $recvHead[hd2];//content len
70 $this->opcode = $recvHead[pa1];//opcode
71 $this->params = $recvHead[pa2];//params
72
73 $this->pos = 12;//去除包头长度
74
75 if ($SD != 21316)
76 {
77 return false;
78 }
79 }else
80 {
81 $this->pos = 0;
82 }
83 return true;
84 }
85 public function GetOP()
86 {
87 if ($this->buf)
88 {
89 return $this->opcode;
90 }
91 return 0;
92 }
93 /************************private***************************/
94 //构造包头
95 private function MakeHead($opcode,$param)
96 {
97 return pack("SSII","SD",$this->TellPut(),$opcode,$param);
98 }
99
100 //用以模拟函数重载
101 private function __call($name, $arg)
102 {
103 return call_user_func_array(array($this, $name), $arg);
104 }
105
106
107 /***********************Uitl***************************/
108 //将16进制的op转成10进制
109 static function MakeOpcode($MAJOR_OP, $MINOR_OP)
110 {
111 return ((($MAJOR_OP & 0xffff) << 16) | ($MINOR_OP & 0xffff));
112 }
113 }
114 /**
115 * 包体类
116 * 包含了对包体的操作
117 */
118 class ContentHandler
119 {
120 public $buf;
121 public $pos;
122 public $contentlen;//use for unpack
123
124 function __construct()
125 {
126 $this->buf = "";
127 $this->contentlen = 0;
128 $this->pos = 0;
129 }
130 function __destruct()
131 {
132 unset($this->buf);
133 }
134
135 public function PutInt($int)
136 {
137 $this->buf .= pack("i",(int)$int);
138 }
139 public function PutUTF($str)
140 {
141 $l = strlen($str);
142 $this->buf .= pack("s",$l);
143 $this->buf .= $str;
144 }
145 public function PutStr($str)
146 {
147 return $this->PutUTF($str);
148 }
149
150
151 public function TellPut()
152 {
153 return strlen($this->buf);
154 }
155
156
157 /*******************************************/
158
159 public function GetInt()
160 {
161 //$cont = substr($out,$l,4);
162 $get = unpack("@".$this->pos."/i",$this->buf);
163 if (is_int($get[1])){
164 $this->pos += 4;
165 return $get[1];
166 }
167 return 0;
168 }
169 public function GetShort()
170 {
171 $get = unpack("@".$this->pos."/S",$this->buf);
172 if (is_int($get[1])){
173 $this->pos += 2;
174 return $get[1];
175 }
176 return 0;
177 }
178 public function GetUTF()
179 {
180 $getStrLen = $this->GetShort();
181
182 if ($getStrLen > 0)
183 {
184 $end = substr($this->buf,$this->pos,$getStrLen);
185 $this->pos += $getStrLen;
186 return $end;
187 }
188 return '';
189 }
190 /***************************/
191
192 public function GetBuf()
193 {
194 return $this->buf;
195 }
196
197 public function SetBuf($strBuf)
198 {
199 $this->buf = $strBuf;
200 }
201
202 public function ResetBuf(){
203 $this->buf = "";
204 $this->contentlen = 0;
205 $this->pos = 0;
206 }
207
208 }
209
210 ?>
可能你看的有点迷糊,因为我也不知道该怎么解释,有空梳理一下。