看了HTTPSQS,自己尝试开发了队列服务器。原理是借鉴HTTPSQS,只是通信协议层没有使用HTTP协议,而是自己的定的协议规则。
一是为了练手,练习检测内存泄露同时巩固指针的使用。
二是为了理解通信协议。
目前只支持Windows下的编译,后面会支持Linux。
我每次都是先在windows下开发,之后再到调试支持linux下的编译。因为Linux的桌面版真心蛋疼,还不如直接windows下开发,然后通过虚拟机下的调试来支持Linux快。
现有支持的功能:
1.创建队列
2.获取队列
3.插入队列
4.删除队列
5.清空队列
6.队列状态
后续还会支持事务,事务与队列的关系可以参考Redis的设计实现:http://www.redisbook.com/en/latest/feature/transaction.html
一、开发用到的库
1、libevent:通信框架
2、glib:跨平台的基础库
3、Tokyo Cabinet:高效的数据存储
二、服务器端通信协议及队列原理
通信协议图:
单个队列图:
多个队列间的关系图直接借用HTTPSQS的:
三、PHP客户端的请求
<?php define('QUEUE_MAX_LENGTH', 10000); class QueueSocket{ private $socket; private $errmsg; public function __construct($host, $port){ $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_bind($this->socket, $host); if(!socket_connect($this->socket, $host, $port)){ $this->set_errmsg("Unable to connect<pre>".socket_strerror(socket_last_error())."</pre>"); return false; } return true; } public function send($cmd, $content){ if(!is_array($content) || !$content) { return false; } $params = false; foreach($content as $key=>$value){ $params[] = strtoupper($key)."={$value}"; } $params = join('&', $params)."\r\n"; $binary = pack("a20i1a*", strtoupper($cmd), strlen($params), $params); socket_write($this->socket, $binary, strlen($binary)); } public function read(){ $response = socket_read($this->socket, 256, PHP_BINARY_READ); if($response) { $response = json_decode($response, true); }else{ return false; } if(isset($response['errno']) && $response['errno'] > 0) $this->set_errmsg($response['errmsg']); return $response; } public function set_errmsg($msg){ $this->errmsg = $msg; } public function get_errmsg(){ return $this->errmsg; } public function __destory(){ socket_close($this->socket); } } class QueueClient extends QueueSocket{ private $appkey; public function __construct($host, $port, $appkey){ $this->appkey = $appkey; parent::__construct($host, $port); } public function create_new_queue($queue_name, $max_length = QUEUE_MAX_LENGTH){ $this->send("CREATE", array('queue_name'=>$queue_name, 'max_length'=>$max_length, 'appkey'=>$this->appkey)); return $this->read(); } public function delete_queue($queue_name){ $this->send("DELETE", array('queue_name'=>$queue_name, 'appkey'=>$this->appkey)); return $this->read(); } public function clear_queue($queue_name){ $this->send("CLEAR", array('queue_name'=>$queue_name, 'appkey'=>$this->appkey)); return $this->read(); } public function put_queue($queue_name, $data){ if(is_array($data) || is_object($data)) $data = serialize($data); $this->send("PUT", array('queue_name'=>$queue_name, 'data'=>$data, 'appkey'=>$this->appkey)); return $this->read(); } public function get_queue($queue_name){ $this->send("GET", array('queue_name'=>$queue_name, 'appkey'=>$this->appkey)); return $this->read(); } public function state($queue_name){ $this->send("STATE", array('queue_name'=>$queue_name, 'appkey'=>$this->appkey)); return $this->read(); } } $queue_client = new QueueClient("localhost", 8080, 'testkey'); //test create queue $result = $queue_client->create_new_queue("test_queue", 10000); print_r($result); //test put for($i=0; $i<100; $i++){ $result = $queue_client->put_queue("test_queue", "jinyong"); print_r($result); } // test get_queue for($i=0; $i<100; $i++){ $result = $queue_client->get_queue("test_queue"); print_r($result); } // test state_queue $result = $queue_client->state("test_queue"); print_r($result); // test clear_queue $queue_client->clear_queue("test_queue");
下面是客户端请求结果的部分截图:
队列服务器软件下载:http://yunpan.cn/QWsgA3iYXXZ5A
队列服务器源码、PHP客户端源码下载:http://yunpan.cn/QWsgy2UU5NhSE
作者:a600423444 发表于2013-4-17 1:21:58 原文链接
阅读:131 评论:0 查看评论