Home >Backend Development >PHP Tutorial >Using PHP message queue to implement Android and Web communication_PHP tutorial
The requirement description is simple: Android sends data to the Web page.
System: Ubuntu 14.04 apache2 php5 Android 4.4
The idea is that the socket message queue server sends events. The following steps are Android side, server side, and front end. The focus is on PHP inter-process communication.
The Android side is relatively straightforward, it is a socket program. It should be noted that if you create a socket directly in the active main thread, an android.os.NetworkOnMainThreadException will be reported. Therefore, the best way is to open a sub-thread to create the socket. The code is as follows
private Socket socket = null; private boolean connected = false; private PrintWriter out; private BufferedReader br; private void buildSocket(){ if(socket != null) return; try { socket = new Socket("223.3.68.101",54311); //IP地址与端口号 out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( socket.getOutputStream())), true); br = new BufferedReader( new InputStreamReader(socket.getInputStream())); } catch (IOException e) { e.printStackTrace(); } connected = true; }
Then send the message
public void sendMsg(String data){ if(!connected || socket == null) return; synchronized (socket) { try { out.println(data); } catch (Exception e) { e.printStackTrace(); } } }
You also need to close the socket after completion
private void closeSocket(){ if( socket == null) return; try { socket.close(); out.close(); br.close(); } catch (IOException e) { e.printStackTrace(); } socket = null; connected = false; }
The following is the server PHP side.
First you need to run a process to receive the information.
function buildSocket($msg_queue){ $address = "223.3.68.101"; $port = 54321; if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false){ echo "socket_create() failed:" . socket_strerror(socket_last_error()) . "/n"; die; } echo "socket create\n"; if (socket_set_block($sock) == false){ echo "socket_set_block() faild:" . socket_strerror(socket_last_error()) . "\n"; die; } if (socket_bind($sock, $address, $port) == false){ echo "socket_bind() failed:" . socket_strerror(socket_last_error()) . "\n"; die; } if (socket_listen($sock, 4) == false){ echo "socket_listen() failed:" . socket_strerror(socket_last_error()) . "\n"; die; } echo "listening\n"; if (($msgsock = socket_accept($sock)) === false) { echo "socket_accept() failed: reason: " . socket_strerror(socket_last_error()) . "\n"; die; } $buf = socket_read($msgsock, 8192); while(true){ if(strlen($buf) > 1) handleData($buf,$msg_queue); //见后文 $buf = socket_read($msgsock, 8192); //看情况 break 掉 } socket_close($msgsock); }
The main program of the script is written like this.
$msg_queue_key = ftok(__FILE__,'socket'); //__FILE__ 指当前文件名字 $msg_queue = msg_get_queue($msg_queue_key); //获取已有的或者新建一个消息队列 buildSocket($msg_queue); socket_close($sock);The ftok() function is to generate a queue key to distinguish.
Then the task of handleData() is to put the received message into the queue
function handleData($dataStr, $msg_queue){ msg_send($msg_queue,1,$dataStr); }Socket process script skeleton
<!--?php //socket.php 服务器进程 function buildSocket($msg_queue){ } function handleData($dataStr, $msg_queue){ } set_time_limit(0); $msg_queue_key = ftok(__FILE__,'socket'); $msg_queue = msg_get_queue($msg_queue_key); buildSocket($msg_queue); socket_close($sock); ?-->
In this way, other processes can find this queue through key and read messages from it. Use this to make it readable
function redFromQueue($message_queue){ msg_receive($message_queue, 0, $message_type, 1024, $message, true, MSG_IPC_NOWAIT); echo $message."\n\n"; } $msg_queue_key = ftok("socket.php", 'socket'); //第一个变量为上方socket进程的文件名。 $msg_queue = msg_get_queue($msg_queue_key, 0666); while(true){ $msg_queue_status = msg_stat_queue($msg_queue); //获取消息队列的状态 if($msg_queue_status["msg_qnum"] == 0) //如果此时消息队列为空,那么跳过,否则会读取空行。 continue; redFromQueue($msg_queue); }
var source = new EventSource("php/getData.php"); //Web 服务器路径 source.onmessage = function(event){ //消息事件回调 var resData = event.data; document.getElementById("res").innerHTML=resData; };
<!--?php //getData.php,提供给 Web 请求使用。 //声明文档类型 header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); function redFromQueue($message_queue){ msg_receive($message_queue, 0, $message_type, 1024, $message, true, MSG_IPC_NOWAIT); echo "data:".$message."\n\n"; //注意一定要在数据前面加上 “data:” flush(); //立刻 flush 一下 } $msg_queue_key = ftok("socket.php", 'socket'); $msg_queue = msg_get_queue($msg_queue_key, 0666); echo "data:connected\n\n"; flush(); while(true){ $msg_queue_status = msg_stat_queue($msg_queue); if($msg_queue_status["msg_qnum"] == 0) continue; redFromQueue($msg_queue); } ?-->
Now you can start running, first run the server
php socket.php
After printing listening, you can connect using an Android device.
Then use JS on the Web to request the getData script. After the request, the frontend can continuously obtain new data. It should be noted that the message queue may be blocked (the message volume reaches the upper limit), and there are limitations of the JS message mechanism itself, so losses, delays and other phenomena occur frequently.
The old problem of Web communication is stability. In the past, I always resented Web QQ for packet dropping. In fact, the entire Web revolution has not yet succeeded.