[前回の続き]
(https://qiita.com/tako3pro/items/08961c5dc7a8d398b859)
使用したツールなど
前の記事を参照
やりたかったこと
- 「非同期」にする。
- 「POST形式」で送信する。
- 「クラス」にする。
コード
クライアント:
main.cpp
# include <iostream>
# include <vector>
# include <iomanip>
# include <boost/asio.hpp>
# include <boost/bind.hpp>
# include <boost/algorithm/string.hpp>
# include "json11.hpp"
using namespace std;
namespace asio = boost::asio;
using asio::ip::tcp;
class Client {
asio::io_service& io_service_;
tcp::socket socket_;
tcp::resolver resolver_;
asio::streambuf sendbuf_;
asio::streambuf recvbuf_;
int value1, value2;
const string post = "addapp.php";
const string host = "127.0.0.1";
public:
Client(asio::io_service& io_service, int v1, int v2)
: io_service_(io_service),
socket_(io_service),
resolver_(io_service),
value1(v1),
value2(v2)
{
}
void connect()
{
tcp::resolver::query query(host, "http");
resolver_.async_resolve(
query,
boost::bind(&Client::on_resolve, this,
asio::placeholders::error,
asio::placeholders::iterator));
}
private:
void on_resolve(const boost::system::error_code& error,
tcp::resolver::iterator endpoint_iterator)
{
/*if (error) {
cout << "resolve failed: " << error.message() << endl;
return;
}*/
asio::async_connect(
socket_,
endpoint_iterator,
boost::bind(&Client::on_connect, this, asio::placeholders::error));
}
void on_connect(const boost::system::error_code& error)
{
/*if (error) {
cout << "connect error : " << error.message() << endl;
}
else {
cout << "connect!" << endl;
}*/
//リクエストを送信
async_send();
//レスポンスを受信
async_recv();
}
void async_send() {;
ostream request_stream(&sendbuf_);
string query = "value1=" + to_string(value1) + "&value2=" + to_string(value2);
request_stream << "POST " << post << " HTTP/1.1\r\n";
request_stream << "Host: " << host << "\r\n";
request_stream << "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n";
request_stream << "Content-Length: " << query.length() << "\r\n";
request_stream << "Connection: Close\r\n";
request_stream << "\r\n";
request_stream << query << "\r\n";
asio::async_write(socket_, sendbuf_.data(), boost::bind(&Client::send_end, this, asio::placeholders::error));
}
void send_end(const boost::system::error_code& error) {
//cout << "request : " << asio::buffer_cast<const char*>(sendbuf_.data()) << endl;
sendbuf_.consume(sendbuf_.size());
}
void async_recv() {
asio::async_read(socket_, recvbuf_, asio::transfer_all(), boost::bind(&Client::recv_end, this, asio::placeholders::error));
}
void recv_end(const boost::system::error_code& error) {
//cout << "response : " << asio::buffer_cast<const char*>(recvbuf_.data()) << endl;
string_to_json(asio::buffer_cast<const char*>(recvbuf_.data()));
recvbuf_.consume(recvbuf_.size());
}
void string_to_json(string str) {
vector<string> res;
res = boost::split(res, str, boost::is_any_of("\r\n\r\n"));
string err;
const json11::Json jsonData = json11::Json::parse(res[res.size() - 1], err);
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';
}
}
};
int main()
{
asio::io_service io_service;
int value1, value2;
cin >> value1 >> value2;
Client client(io_service, value1, value2);
client.connect();
io_service.run();
}
サーバー:
add.php
<?php
//計算する値を入力
$isInput = TRUE;
if(isset($_POST['value1'])){
$value1 = intval($_POST['value1']);
}
else {
$isInput = FALSE;
}
if(isset($_POST['value2'])){
$value2 = intval($_POST['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;
?>
変更点など
出力結果は前回と同じである。
main.cppは、目的である「非同期」「POST形式」「クラス」を満たすようにした。
エラー発生時のコメントは表示しない。
app.phpは、「$_GET」の部分を「$_POST」にしただけである。
まとめ
この書き方が正しいかは分からないが取り敢えず実行はできた。
これを使って簡単なゲームでも作りたい。
参考にしたサイト
・[ネットワーク - TCP]
(https://boostjp.github.io/tips/network/tcp.html)
・[Boost.Asio ゲームループで非同期操作を行う]
(https://faithandbrave.hateblo.jp/entry/20110325/1301036991)