一般来说PHP适用的场合是web页面展示等耗时比较短的任务,如果对于比较花时间的操作如大量数据导入、发送邮件等,就很容易出现操作超时的情况。这些耗时的任务我们并不需要关注他的进度,只需要让他在后台慢慢的进行就可以了。我们可以使用文件来保存一个任务队列,或者把任务队列保存在数据库中,然后后台服务不断的检查这个任务队列,但是这样效率会比较差,这时候可以使用socket的方式来实现异步操作。当有新任务需要进行的时候,client向服务器端发送一个消息,通知服务器端进行相应的任务,服务器端收到消息之后返回一个状态码,通知客户端任务创建成功,这时客户端就可以断开连接了,这要就不会出现网页阻塞等待任务的执行。
后台构建socket服务端,当然这个可以用任何一种后台语言实现,对于php这种语言总觉得做后台服务不好,但是也不是不可以,这里只是一个例子,socket服务端我们可以使用C/C++、Java或Python等任何一种效率更高的语言来实现。
<?php /** * Server端 */ class SocketServer{ private $_port=9000; private $_address='127.0.0.1'; private $_client_socket_list=array(); public function __set($name,$val){ $this->$name=$val; } private function _showError($error){ exit($error); } public function start(){ if (($sock = socket_create ( AF_INET, SOCK_STREAM, SOL_TCP )) === false) { $this->_showError("socket_create() failed :reason:" . socket_strerror ( socket_last_error () )); } if (socket_bind ( $sock, $this->_address, $this->_port ) === false) { $this->_showError("socket_bind() failed :reason:" . socket_strerror ( socket_last_error ( $sock ) )); } if (socket_listen ( $sock, 5 ) === false) { $this->_showError("socket_bind() failed :reason:" . socket_strerror ( socket_last_error ( $sock ) ) ); } echo "SERVER RUN SUCCESS! IP:{$this->_address} PORT:{$this->_port}\r\n"; do { if ($client_socket=socket_accept ( $sock )) { $count = count ( $this->_client_socket_list ) + 1; $this->_client_socket_list[]=$client_socket; echo "NEW CONNECTION:\r\n"; echo "CURRENT CONNECTION:{$count}\r\n"; $msg=$this->read($client_socket); echo "CLIENT_MSG:{$msg}\r\n"; $my_msg=json_encode(array('status'=>1))."\r\n"; $this->send($client_socket,$my_msg); //进行相应的任务操作 } } while(true); } public function send($client_socket,$str){ return socket_write ( $client_socket,$str, strlen ( $str ) ); } public function read($client_socket){ return socket_read ( $client_socket, 8192 ); } } $socket_server =new SocketServer(); $socket_server->start(); ?>
客户端代码:
<?php $fp = fsockopen("127.0.0.1", 9000, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />\n"; } else { $out = "doubi"; fwrite($fp, $out); while (!feof($fp)) { $msg = json_decode(fgets($fp, 128)); print_r($msg); if($msg->status==1){ break; } } } fclose($fp); ?>
转载请注明出处fullstackdevel.com:SEAN是一只程序猿 » php用socket实现异步任务操作
评论前必须登录!