備忘録

備忘録

mongooseを利用してHTTPサーバを構築する方法

Ⅰ. はじめに

タイトルの通り「mongooseを利用してHTTPサーバを構築する方法」です。

Ⅱ. やり方

1. サンプルプログラムを書く
#include <iostream>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
extern "C" {
#include <mongoose.h>
}

static void fn(struct mg_connection* c, int ev, void* ev_data, void* fn_data) {
  if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message* hm = (struct mg_http_message*)ev_data;
    if (mg_http_match_uri(hm, "/test1")) {
      // "ok"を返す
      mg_http_reply(c, 200, "", "ok");
    }
    else if (mg_http_match_uri(hm, "/test2")) {
      // "helloworld"を返す
      std::string str("helloworld");
      mg_printf(c, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n", str.size());
      mg_send(c, str.c_str(), str.size());
    }
    else if (mg_http_match_uri(hm, "/test3")) {
      // bodyをそのまま返す
      mg_printf(c, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n", hm->body.len);
      mg_send(c, hm->body.ptr, hm->body.len);
    }
  }
}

int main() {
  // Initialise event manager
  struct mg_mgr mgr;
  mg_mgr_init(&mgr);

  // Create HTTP listener
  mg_http_listen(&mgr, "http://0.0.0.0:80", fn, NULL);

  // Infinite event loop
  while (true) {
    mg_mgr_poll(&mgr, 1000);
  }

  return 0;
}

実行結果1

GET http://127.0.0.1/test1 HTTP/1.1
Host: 127.0.0.1
HTTP/1.1 200 OK
Content-Length: 2

ok

実行結果2

GET http://127.0.0.1/test2 HTTP/1.1
Host: 127.0.0.1
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 10

helloworld

実行結果3

POST http://127.0.0.1/test3 HTTP/1.1
Host: 127.0.0.1
Content-Length: 11

HelloWorld!
HTTP/1.1 200 OK
Content-Length: 11

HelloWorld!

VisualStudioを利用してAndroidで実行可能な実行ファイルをC++で作成する方法

Ⅰ. はじめに

タイトルの通り「VisualStudioを利用してAndroidで実行可能な実行ファイルをC++で作成する方法」です。

Ⅱ. やり方

1. Visual Studio Installerを起動する
2. 「C++ によるモバイル開発」をインストールする

f:id:kagasu:20210404210310p:plain

3. 「メイクファイル プロジェクト(Android)」を選択する

f:id:kagasu:20210404210636p:plain

4. サンプルプログラムを書く

f:id:kagasu:20210412170848p:plain

$(project_root)/jni/Android.mk

# https://developer.android.com/ndk/guides/android_mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := helloworld
LOCAL_SRC_FILES := ../src/main.cpp
LOCAL_CFLAGS += -fPIE
LOCAL_LDFLAGS += -fPIE -pie
# LOCAL_LDLIBS := -lz
# LOCAL_CPP_FEATURES := exceptions

include $(BUILD_EXECUTABLE)

$(project_root)/jni/Application.mk

# https://developer.android.com/ndk/guides/application_mk
APP_ABI := armeabi-v7a arm64-v8a
APP_PLATFORM := android-16
APP_OPTIM := release
APP_STL := c++_static

$(project_root)/src/main.cpp

#include <iostream>

int main()
{
  std::cout << "Hello world!" << std::endl;
  return 0;
}
5. ビルドする

実行結果

$ ./helloworld 
Hello world!

FAQ

Q1. Android SDK, Android NDKディレクトリはどこで設定できますか?

A1. VisualStudioのオプションから設定可能です。
f:id:kagasu:20210404211641p:plain

Q2. VisualStudioを利用したくないです。

A2. この記事と同じディレクトリ構成のディレクトリを作成し、$(project_root)で以下コマンドを実行するとビルド出来ます。

ndk-build
Q3. ndk-buildはどこにありますか?

A3. 以下パスに存在します

$(ANDROID_SDK_ROOT)\ndk\$(ndk_version)
例. C:\Android\ndk\21.1.6352462

AndroidStudioを利用してAndroidで実行可能な実行ファイルをC++で作成する方法

Ⅰ. はじめに

タイトルの通り「AndroidStudioを利用してAndroidで実行可能な実行ファイルをC++で作成する方法」です。

Ⅱ. やり方

1. 新規Native C++プロジェクトを作成する

f:id:kagasu:20210404175719p:plain

2. CMakeLists.txtを編集する

$(project_root)/app/src/main/cpp/CMakeLists.txt

cmake_minimum_required(VERSION 3.10.2)
project("helloworld")

add_executable(helloworld native-lib.cpp)
find_library(log-lib log)
target_link_libraries(helloworld ${log-lib})
3. サンプルプログラムを書く

$(project_root)/app/src/main/cpp/native-lib.cpp

#include <iostream>

int main()
{
  std::cout << "Hello world!" << std::endl;
  return 0;
}
4. ビルドする
5. 実行ファイルをAndroidにコピーする
adb push ^
  $(project_root)\app\.cxx\cmake\debug\arm64-v8a\helloworld ^
  /sdcard/

実行結果

$ ./helloworld 
Hello world!

FAQ

Q1. armeabi-v7aとarm64-v8aだけビルドしたい

A1. build.gradle(Module)を以下の通り編集する

android {
  defaultConfig {
    ndk {
      abiFilters 'armeabi-v7a', 'arm64-v8a'
    }
  }
}

C++のHTTPサーバ、HTTPクライアントライブラリ一覧

Ⅰ. はじめに

タイトルの通り「C++のHTTPサーバ、HTTPクライアントライブラリ一覧」です。

Ⅱ. 一覧

cpp-httplib
  • HTTP Server/Client
  • ヘッダファイルのみ
  • Android NDKで問題なく利用できた
Drogon
  • HTTP Server(Web Framework)
Oat++
mongoose
  • HTTP Server/Client, WebSocket Server/Client, MQTT Server/Client, Socks5 Server
  • 2ファイルのみ(ヘッダとソース)
  • 幅広い採用実績がある(OSS, 商用, 国際宇宙ステーション
  • Android NDKで問題なく利用できた
civetweb
  • HTTP Server
  • 2ファイルのみ(ヘッダとソース)
  • mongooseのfork
  • CGI, Luaをサポート

Chrome拡張機能でProxy設定情報を取得する方法

Ⅰ. はじめに

タイトルの通り「Chrome拡張機能でProxy設定情報を取得する方法」です。

Ⅱ. やり方

1. サンプルプログラムを書く

manifest.json

{
  "manifest_version": 2,
  "name": "ChromeTestExtension",
  "version": "1.0.0",
  "background": {
    "scripts": [ "scripts/background.js" ]
  },
  "content_scripts": [
    {
      "js": [ "scripts/content_script.js" ],
      "matches": [ "*://example.com/*" ],
      "run_at": "document_end"
    }
  ],
  "permissions": [ "tabs", "proxy" ]
}

scripts/background.js

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  switch (message.action) {
    case 'get_proxy_info':
      chrome.proxy.settings.get({ 'incognito': false }, (config) => {
        sendResponse(config)
      })
      break
  }

  return true
})

scripts/content_script.js

chrome.runtime.sendMessage({ action: "get_proxy_info" }, result => {
  console.log(result)
})

実行結果

Proxy設定情報の取得に成功し、システムの設定値が使用されている事がわかる
f:id:kagasu:20210401140046p:plain