タイトルの通り、C++とPHPとMySQLを用いてデータのやり取りをやってみたのでメモ。
#使用したもの
ツール
・VisualStudio2017
・Xampp
ライブラリ
・Boost (通信するために使用)
・Json11 (JSONを解析するために使用)
#やりたいこと
流れとしては、
①C++ → ②PHP → ③MySQL → ④PHP → ⑤C++ の順でデータをやり取りしたい。
取りあえず、今回は2つの値を足し算した結果を取得することを目標とする。
① 足し算したい2つの値を入力し、GET方式で送る。
② 足し算を行い、MySQLに計算結果を送る。
③ 結果を保存する。
④ 今までの計算結果を受け取り、JSON形式で送る。
④ JSON形式で計算結果を受け取り、それらを表示する。
#コード
クライアント:
#include <iostream>
#include <iomanip>
#include <boost/asio.hpp>
#include <boost/algorithm/string.hpp>
#include <vector>
#include "json11.hpp"
using namespace std;
namespace asio = boost::asio;
namespace ip = asio::ip;
using namespace json11;
int main()
{
//足し算する値の入力
int value1, value2;
cout << "value1を入力 : "; cin >> value1;
cout << "value2を入力 : "; cin >> value2;
cout << '\n';
//リクエストに対するレスポンス
string allRes = "";
//通信を開始
try {
asio::io_service io_service;
//TCPソケットを作成する
ip::tcp::socket sock(io_service);
//名前解決(ホスト名からIPアドレスに変換)する
ip::tcp::resolver resolver(io_service);
ip::tcp::resolver::query query("127.0.0.1", "http");
//ホスト情報を設定する
ip::tcp::endpoint endpoint(*resolver.resolve(query));
//ソケットへ接続
sock.connect(endpoint);
//メッセージを送信
asio::streambuf request;
ostream request_ostream(&request);
string getRequest = "GET add.php?value1=" + to_string(value1)
+ "&value2=" + to_string(value2) + " HTTP/1.0\r\n\r\n";
request_ostream << getRequest;
asio::write(sock, request);
//メッセージを受信
asio::streambuf response;
boost::system::error_code error;
while (asio::read(sock, response, asio::transfer_at_least(1), error)) {
//streambufからstringに変換
string tmp = asio::buffer_cast<const char *>(response.data());
allRes += tmp.substr(0, response.size());
}
}
catch (exception& e) {
cout << e.what() << '\n';
return 1;
}
//二重改行で区切る(レスポンスボディを取得するため)
vector<string> res;
res = boost::split(res, allRes, boost::is_any_of("\r\n\r\n"));
//stringからJsonに変換
string err;
const Json jsonData = Json::parse(res[res.size() - 1], err);
cout << jsonData.dump() << "\n\n";
//各値を取得
auto jsonArray = jsonData.array_items();
cout << " id value1 value2 ans" << endl;
for (auto &item : jsonArray) {
cout << setw(6) << right << item["id"].string_value() << " ";
cout << setw(6) << right << item["value1"].string_value() << " ";
cout << setw(6) << right << item["value2"].string_value() << " ";
cout << setw(6) << right << item["ans"].string_value() << '\n';
}
return 0;
}
MySQLに「calc_db」というデータベースを作り、テーブル名を「result」とした。
カラムは、「id」「value1」「value2」「ans」の4つである。
これにより、挿入された順番、入力した値、二つの値の足し算の結果がDBに保存される。
サーバー:
<?php
//計算する値を入力
$isInput = TRUE;
if(isset($_GET['value1'])){
$value1 = intval($_GET['value1']);
}
else {
$isInput = FALSE;
}
if(isset($_GET['value2'])){
$value2 = intval($_GET['value2']);
}
else {
$isInput = FALSE;
}
//DBの設定
$mysql = mysqli_connect('localhost', 'root', '') or die(mysqli_error($mysql));
mysqli_select_db($mysql, 'calc_db');
mysqli_query($mysql, 'SET NAMES UTF8');
//入力があるならデータをDBに追加
if($isInput){
//結果を計算
$ans = $value1 + $value2;
//DBにデータを挿入
$insert = sprintf('INSERT INTO result SET value1=%d,value2=%d,ans=%d',
mysqli_real_escape_string($mysql, $value1),
mysqli_real_escape_string($mysql, $value2),
mysqli_real_escape_string($mysql, $ans)
);
mysqli_query($mysql, $insert) or die(mysqli_error($mysql));
}
//DBからデータを取得
$request = sprintf('SELECT * FROM result');
$result = mysqli_query($mysql, $request) or die(mysqli_error($mysql));
$ansList = array();
while($row = mysqli_fetch_assoc($result)){
$ansList[] = array(
'id'=>$row['id'],
'value1'=>$row['value1'],
'value2'=>$row['value2'],
'ans'=>$row['ans']
);
}
//jsonで出力
$jsonData = json_encode($ansList);
header("Content-Type: application/json; charset=utf-8");
echo $jsonData;
?>
#出力結果
value1に「1」、value2に「2」を入力した。
足し算をした結果、ansが「3」となっていることが分かる。
value1を入力 : 1
value2を入力 : 2
[{"ans": "3", "id": "1", "value1": "1", "value2": "2"}]
id value1 value2 ans
1 1 2 3
次に、value1に「2」、value2に「3」を入力した。
ansは「5」となり、表にはこれまでの計算結果が表示されている。
value1を入力 : 2
value2を入力 : 3
[{"ans": "3", "id": "1", "value1": "1", "value2": "2"}, {"ans": "5", "id": "2", "value1": "2", "value2": "3"}]
id value1 value2 ans
1 1 2 3
2 2 3 5
データベースの中身は以下ようになっている。
#まとめ
C++からPHP、PHPからMySQLへの連携は簡単ながら行うことができた。
GET形式をPOST形式にしたり、同期通信を非同期通信にするなどまだやることはある。
また、コードに関してももっと良い書き方があると思う。
今度はこれを応用して何か作りたい。
#参考にしたサイト
・[ネットワーク - TCP]
(https://boostjp.github.io/tips/network/tcp.html)
・[Boost.AsioでHTTP通信]
(https://nekko1119.hatenablog.com/entry/2013/10/02/145532)
・[C++11でjsonを扱う方法。json11]
(https://qiita.com/YukiMiyatake/items/497e2fe807d09141e000)
・[C++11でjson扱うならdropbox/json11がよさそう]
(https://kyokomi.hatenablog.com/entry/2014/05/10/233613)
など。