<?php
set_time_limit(0);
error_reporting(E_ERROR);require_once 'conf/db_conf.php';$address = '127.0.0.1';
$port = 1919;$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>3, "usec"=>0 ));
socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array("sec"=>3, "usec"=>0 ));
socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);socket_bind($sock, $address, $port);
socket_listen($sock);$clients = array($sock);$ark_port_map = array();while (true){
$loop_start_time = time();
$read = $clients;
if (count($read) < 1){
break;
}
if (socket_select($read, $write = NULL, $except = NULL, NULL) < 1){
continue;
}
/**
* 建立连接
*/
if (in_array($sock, $read)){
$clients[] = $new_sock = socket_accept($sock);
$key_in_read = array_search($sock, $read);
unset($read[$key_in_read]);
}
/**
* 如果是首次连接,客户端发送01,
* 将建立连接的设备的设备号与其ip和端口作匹配。
*
* 将要开启的设备号和盒子号数组被保存到了数据库中,
* 数组格式为array('arkid' => array('cabid1', 'cabid2'))。
* 根据数组中匹配的设备号发送开锁数据到设备客户端。
*
* 将要更新的设备号数组被保存到了数据库中,
* 数组格式为array('0001', '0003')。
* 根据数组中匹配的设备号发送更新数据到设备客户端。
*/
/**
* 1.查询将要开启的盒子的json数组
* 2.查询将要更新的设备的json数组
*/
$msi_cached = get_connection();
$sql_cached = "select cached_goods, updating_arks from imicms_yh_saling_goods";
$res_cached = $msi_cached->query($sql_cached);
$cached_goods_json = '';
$updating_arks_json = '';
if ($datarow_cached = $res_cached->fetch_array()){
$cached_goods_json = $datarow_cached[0];
$updating_arks_json = $datarow_cached[1];
}
$msi_cached->close();
$opening_arksandcabs_arr = json_decode($cached_goods_json, true);
$updating_arks_arr = json_decode($updating_arks_json, true);
foreach ($read as $read_sock){
socket_getpeername($read_sock, $read_sock_ip, $read_sock_port);
$recv_count=socket_recv($read_sock, $sock_data, 2048, 0);
/**
* 如果从客户端接收数据失败,
* 并且从上一次接受数据到现在时间大于60秒,
* 则服务器认为该客户端已断开连接,
* 将该链接从clients数组中去除,
* 同时将链接从ip端口-设备匹配数组中去除。
*/
if (($recv_count < 0 || $recv_count == false) && time() - $loop_start_time > 60){
$key_in_clients = array_search($read_sock, $clients);
unset($clients[$key_in_clients]);
unset($ark_port_map[$read_sock_ip . $read_sock_port]);
continue;
}elseif ($recv_count < 0 || $recv_count == false){
continue;
} $key_arkid = $ark_port_map[$read_sock_ip . $read_sock_port]['arkid'];
$sock_data = trim($sock_data);
$sock_data_arr = explode(',', $sock_data);
/**
* 如果发来的数据为01,将建立连接的设备的设备号与其ip和端口作匹配。
* 处理发送过来的数据时,若有返回数据,
* 返回数据完成均跳转到下一次foreach循环
*/
$recv_num = $sock_data_arr[2];
if ($recv_num == '01'){
$new_sock_arkid = $sock_data_arr[1];
$ark_port_map[$read_sock_ip . $read_sock_port]['arkid'] = $new_sock_arkid;
$send_data_first_return = "%S,$new_sock_arkid,02,ok";
$send_count_first_return = socket_send($read_sock, $send_data_first_return, strlen($send_data_first_return), 0);
continue;
}elseif ($recv_num == '10' || $recv_num == '20' || $recv_num == '30' || $recv_num == '40' || $recv_num == '50'){ /**
* 如果发来的数据为10到50,判断对应盒子的状态并强制开启
* 将设备和盒子的ID放入要开启的盒子的数组中
*/
$force_opening_cabid = substr($recv_num, 0, 1);
$msi_stat = get_connection();
$sql_stat = "select cabstat$force_opening_cabid from imicms_yh_goods where arkid = '$key_arkid'";
$res_stat = $msi_stat->query($sql_stat);
$cabstat = 'Y';
if ($datarow_stat= $res_stat->fetch_array()){
$cabstat = $datarow_stat[0];
}
$msi_stat->close();
if($cabstat == 'Y'){
if (array_key_exists($key_arkid, $opening_arksandcabs_arr)){
if (!in_array($force_opening_cabid, $opening_arksandcabs_arr[$key_arkid])){
$opening_arksandcabs_arr[$key_arkid][] = $key_arkid;
}
}else{
$opening_arksandcabs_arr[$key_arkid] = array($force_opening_cabid);
}
}
}elseif ($recv_num == 'k'){
/**
* 如果发来的数据为k,表示盒子开启成功,
* 从要开启的盒子的数组中删除对应的设备和盒子
*/
$opened_return_cabid = $sock_data_arr[3];
$arr2floor_key = array_search($opened_return_cabid, $opening_arksandcabs_arr[$key_arkid]);
unset($opening_arksandcabs_arr[$key_arkid][$arr2floor_key]);
//如果设备没有要开启的盒子,删除数组中的设备
if (empty($opening_arksandcabs_arr[$key_arkid])){
unset($opening_arksandcabs_arr[$key_arkid]);
}
}elseif ($recv_num == 'h'){ /**
* 如果发来的数据为h,表示设备更新成功,
* 从要更新的设备的数组中删除对应的设备
*/
if (in_array($key_arkid, $updating_arks_arr)){
$key_in_updating = array_search($key_arkid, $updating_arks_arr);
unset($updating_arks_arr[$key_in_updating]);
$updating_arks_arr = array_values($updating_arks_arr);
}
}
/**
* 根据要开启的盒子数组中匹配的设备号发送开锁数据到设备客户端。
*/
if (array_key_exists($key_arkid, $opening_arksandcabs_arr)){
$opening_cabs_arr = $opening_arksandcabs_arr[$key_arkid];
foreach ($opening_cabs_arr as $opening_cab){
$send_data_open = "%S,$key_arkid,$opening_cab,ok";
$send_count = socket_send($read_sock, $send_data_open, strlen($send_data_open), 0);
if($send_count < 0 || $send_count == false){
continue;
}
}
//为了保证每次通讯只调用一次socket_send,此处直接跳转至下一个foreach循环
continue;
}
/**
* 根据将要更新设备数组中的匹配的设备号发送更新命令到客户端。
*/
if (in_array($key_arkid, $updating_arks_arr)){
$send_data_update = "%S,$key_arkid,r,ok";
$send_count_update = socket_send($read_sock, $send_data_update, strlen($send_data_update), 0);
if($send_count_update < 0 || $send_count_update == false){
continue;
}
}
} $msi_cached_now = get_connection();
$sql_cached_now = "select cached_goods, updating_arks from imicms_yh_saling_goods";
$res_cached_now = $msi_cached_now->query($sql_cached_now);
$cached_goods_now_json = '';
$updating_arks_now_json = '';
if ($datarow_cached_now = $res_cached_now->fetch_array()){
$cached_goods_now_json = $datarow_cached_now[0];
$updating_arks_now_json = $datarow_cached_now[1];
}
$msi_cached_now->close();
/**
* 1.重新向数据库写入将要开启的盒子的json数组
* 2.重新向数据库写入将要更新的设备的json数组
*/
$new_cached_goods_json = json_encode($opening_arksandcabs_arr);
$new_updating_arks_json = json_encode($updating_arks_arr);
if ($new_cached_goods_json != $cached_goods_now_json || $new_updating_arks_json != $updating_arks_now_json){
$msi_new_cached = get_connection();
$sql_new_cached = "update imicms_yh_saling_goods set cached_goods = '$new_cached_goods_json', updating_arks = '$new_updating_arks_json'";
$msi_new_cached->query($sql_new_cached);
$msi_new_cached->close();
}
}socket_close($sock);
?>
解决方案 »
- 二叉树的中序遍历
- 输入名字,显示图片
- 【郁闷】这个正则表达式在Regex Tester中能通过, 用preg_replace怎么就出粗呢?
- 为什么我写的翻页上下各翻一页然后就翻不动了?
- 100分问个数据库统计的问题
- 关于“filename.php?mess_id=123”类型描述的问题
- 提供了10G的FTP空间,欢迎大家上传好的资源一起分享。
- 请问在solaris下如何安装php
- 有这样个问题一直没有解决
- 【PHP/VC】急救:在编译php的扩展模块的error LNK2001: unresolved external symbol!!!
- php如何post到url
- PHP报错fopen(C:\data\live_dem...
虽然 socket_select 会等待连接字的变化
但你不断有请求,自然也就不断有相应的数据库操作当然,一旦你没有了请求,自然也就没有了数据库操作。不过你也感觉不到
因此你
if (socket_select($read, $write = NULL, $except = NULL, NULL) < 1){
continue;
}
是没有道理的