Table of Contents
<a id="1"></a>前言
在應用開發的過程中,涉及網絡,常常就需要通過一些 HTTP 請求從網上獲取數據。很多網絡服務器(Web server)提供了 URL 類型的 API,通過訪問特定的 URL,就能從服務器返回數據,比如:
http://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=b1b15e88fa797225412429c1c50c122a1
在瀏覽器訪問上面這個鏈接,服務器就會返回數據。返回的數據類型有很多種,如:JSON,XML等。
本文旨在通過一個例子簡要介紹這種服務器程序的構建,最終完成一個服務器程序,實現通過 URL 與服務器通信,服務器返回 JSON 格式的數據。
<a id="2"></a>問題及需求分析
<a id="21"></a>API
觀察上面的 URL,我們可以發現它可以分為兩個部分。
一是主機地址:http://api.openweathermap.org/data/2.5/weather
。
二是參數:q=London,uk&appid=b1b15e88fa797225412429c1c50c122a1
。
主機地址和參數之間用 ?
隔開。參數又可以分為多個獨立的參數。在這個 URL 中,共包含了兩個參數,分別是 q
和 appid
,等號后面是參數的值。
我們要做的是一個物聯網溫度傳感器的后臺服務器,即根據不同的 URL,返回溫度數據或儲存溫度數據。
假設我們的 API 如下:
獲取最近的一個溫度數據 API:
http://localhost:8888/temperature.php?key=lsw&query=get
返回示例(JSON):
成功:{"status":true,"date":"2016-11-17 19:13:09","value":32.63}
失?。簕"status”:false,”message”:”*"}
備注:”value” 的數據類型是 double
上傳一個溫度數據 API:
http://localhost:8888/temperature.php?key=lsw&query=set&value=27.1
返回示例(JSON):
成功:{"status":true,"message":"setting success"}
失?。簕"status”:false,”message”:”*"}
URL 中的 temperature.php 就是我們即將編寫的網頁文件。key 和 query 是兩個參數,在 query=set 時,還應帶有 value 參數。返回的數據類型是 JSON,以 status 標志操作是否成功,以及附帶有信息或數據。
<a id="22"></a>JSON 數據
JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。它基于ECMAScript的一個子集。 JSON采用完全獨立于語言的文本格式,但是也使用了類似于C語言家族的習慣(包括C、C++、C#、Java、JavaScript、Perl、Python等)。這些特性使JSON成為理想的數據交換語言。 易于人閱讀和編寫,同時也易于機器解析和生成(一般用于提升網絡傳輸速率)。
JSON 數據是可以帶有數據類型的,如上面返回示例中的 value 是一個 double 類型的數據。
<a id="3"></a>實現
<a id="31"></a>本地服務器開發環境:MAMP
MAMP 是經典本地服務器環境的 Mac OS 軟件。MAMP 這幾個首字母代表蘋果的 Mac OS 系統上的 Macintosh、Apache、MySQL 和 PHP。在 Windows 系統上也有相應的開發環境,WAMP。這里以 MAMP 為例進行說明。
MAMP 分免費版和專業版,我們目前只需要用到免費版。安裝完成后運行,點擊 Start Servers 就可以運行本地的服務器。默認的本地服務器地址是:http://localhost:8888
。
在 MAMP 的 Preferences.. -> Web Server -> Document Foot 可以定位到服務器源文件目錄。服務器的程序就保存在這個目錄里。
<a id="32"></a>后臺數據庫 MySQL
為了存儲數據,服務器需要有一個數據庫,并實現與數據庫之間的通信。首先我們用 MAMP 運行本地的服務器,在打開的導航網頁中打開數據庫的管理頁面。
新建一個名為 temperatureData
的數據庫,再新建一個數據表 temperature
,并添加如下字段:
這樣就完成了數據庫的配置,目前只需要儲存溫度信心,因此只配置這幾個條目。
<a id="33"></a>服務器程序
有了數據庫,接下來就要寫服務器程序了。服務器程序需要完成以下幾個部分的內容:
- 連接數據庫,與數據庫通信,實現數據的讀取與存儲。
- 獲取 URL 中的參數,根據不同的參數和參數值執行相應的操作。
- 封裝要返回的信息,以 JSON 形式返回。
具體的程序如下,在關鍵的地方以注釋的方式進行說明。
<?php
//函數:用于把數據封裝為 JSON 格式
function echoJSON($withStatus,$andMessage){
$data = array('status' => $withStatus, 'message' => $andMessage);
$jsonstring = json_encode($data);
header('Content-Type: application/json');
echo $jsonstring;
}
// 配置數據庫
$user = 'root';
$password = 'root';
$db = 'temperatureData';
$host = 'localhost';
$port = 8889;
$link = mysqli_init();
$success = mysqli_real_connect(
$link,
$host,
$user,
$password,
$db,
$port
);
$privateKey = "lsw";
if($success){
//與數據庫連接成功后,獲取 URL 中的參數值,根據參數執行相應的程序。如:$_GET["key"] 用于獲取 URL 中 "key" 的參數值。
$key = $_GET["key"];
if($key == $privateKey){
$query = $_GET["query"];
switch ($query){
case "get":
$result = mysqli_query($link,"SELECT * FROM `Temperature`");
$row = mysqli_fetch_array($result);
$data = array('status' => true, 'date' => $row["Date"], 'value' => (double)$row["Value"]);
$jsonstring = json_encode($data);
header('Content-Type: application/json');
echo $jsonstring;
break;
case "set":
$value = $_GET["value"];
$valueDouble = (double)$value;
if($valueDouble){
mysqli_query($link,"DELETE FROM `Temperature` WHERE 1");
mysqli_query($link,"INSERT INTO `Temperature`(`Date`, `Value`) VALUES (CURRENT_TIMESTAMP,$valueDouble);");
$data = array('status' => true, 'message' => 'setting success');
$jsonstring = json_encode($data);
header('Content-Type: application/json');
echo $jsonstring;
}else{
echoJSON(false,"invalid value");
}
break;
default:
echoJSON(false,"unsupported query");
}
}else{
echoJSON(false,"invalid key");
}
}else{
echoJSON(false,"Connect Error: " . mysqli_connect_error());
}
// 關閉數據庫連接。
mysqli_close($link);
?>
在服務器目錄里新建一個 temperature.php
文件,將上述程序復制到文件中保存。用 MAMP 運行服務器,下面將檢驗我們服務器的配置情況。
在瀏覽器中訪問:http://localhost:8888/temperature.php?key=lsw&query=get 就能獲取數據庫中的溫度信息。如果數據庫中還沒有溫度信息,則會返回如下結果:
{"status":true,"date":null,"value":0}
在瀏覽器中顯示如下:
完整的程序請看這里。
關于如何使用這個 Web 服務器完成物聯網溫度傳感器,請參考:LOT|物聯網 溫度傳感器。
有任何疑問的話,歡迎在下方評論區討論。
附上我的Github:LinShiwei (Lin Shiwei) · GitHub