dasukoの技術ブログ

現役エンジニアのブログです。

【Unity】C#の標準ライブラリのHttpClientを使ってみた

はじめに

今回はプログラミングの話ですが、Unityの話になります。

UnityでHttp通信を行う時には、Unity標準のUnityWebRequestを使うことが多いと思います。

今回はC#標準ライブラリのHttpClientを使ってみたいと思います。

namespace

HttpClientのnamespaceはSystem.Net.Httpです。

実装例

using UnityEngine;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

public class GameManager : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        var task = Task.Run(() =>
        {
            return Get();
        });

        Debug.Log("response:" + task.Result);
    }

    private static async Task<string> Get()
    {
        using (var httpClient = new HttpClient())
        {
            httpClient.BaseAddress = new Uri(URL);
            var response = await httpClient.GetAsync(path);

            if (!response.IsSuccessStatusCode)
            {
                return null;
            }

            var text = await response.Content.ReadAsStringAsync();
            return text;
        }
    }
}

順番に解説していきます。

StartメソッドでGetメソッドのResultを呼ばずに、Taskで実行しているのは、

Resultを呼ぶと、メインスレッドをブロックし合いデッドロックになります。

そのため、Taskで実行することをお勧めします。

C#のTaskについては別の記事で改めてまとめようかと思います。

ちなみにStartメソッドはこのように書いても実行されます。

    async Task Start()
    {
        var result = await Task.Run(() =>
        {
            return Get();
        });

        Debug.Log("response:" + result);
    }

  

Getメソッド内ではHttpClientをusingして使っています。

HttpClientはIDisposableインターフェースを実装しているため、usingのスコープ外に出た時に

リソースを適切に解放するために(Disposeメソッドが自動で呼ばれる)usingを使っています。

今回はBaseAddressを設定していますが、BaseAddressを指定せずに以下のようにGetAsyncメソッドの引数に

URLのフルパスを指定しても問題ありません。

  private static async Task<string> Get()
    {
        using (var httpClient = new HttpClient())
        {
            var response = await httpClient.GetAsync(URL);

            if (!response.IsSuccessStatusCode)
            {
                return null;
            }

            var text = await response.Content.ReadAsStringAsync();
            return text;
        }
    }

ではなぜBaseAddressを指定できるのか。

それはHttpClientのインスタンスは再利用されることが望ましいためです (そのため今回のusingを使ってすぐリソースを解放するような実装は推奨されていません)

あまりにもたくさんのリクエストをすると使用可能なソケット数が枯渇します。

そのため以下のように一つのインスタンスを使い回して実装することが推奨されています。

public class GameManager
{
    private static readonly HttpClient httpClient;

    static GameManager()
    {
        httpClient = new HttpClient();
    }
}

なので、先ほどのサンプルは以下のように書くといいかもしれません。

using UnityEngine;
using System.Net.Http;
using System.Threading.Tasks;
using System;
using System.Net.Http.Headers;

public class GameManager : MonoBehaviour
{
    private static readonly HttpClient httpClient;
    private static readonly string URL = "URL";

    static GameManager()
    {
        httpClient = new HttpClient();
        httpClient.BaseAddress = new Uri(URL);
    }

    // Start is called before the first frame update
    async Task Start()
    {
        var result = await Task.Run(() =>
        {
            return Get(path);
        });

        Debug.Log("response:" + result);
    }


    private static async Task<string> Get(string path)
    {
        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        var response = await httpClient.GetAsync(path);
        if (!response.IsSuccessStatusCode)
        {
            return null;
        }

        var text = await response.Content.ReadAsStringAsync();
        return text;
    }
}

HttpClientは各プラットフォームで最適なトランスポートを使用します。

ホスト/ランタイム バック
Android HttpWebRequestかHttpURLConnectionを使用するかをビルド時に選択
iOS HttpWebRequestかNSUrlSessionを使用するかをビルド時に選択
macOS HttpWebRequest

より詳細を知りたい場合は下記を参照してください。 docs.microsoft.com

HttpClientを参照できない場合

Unityのバージョンによっては、HttpClientが参照できない可能性があります。

その場合はFile > Build Settings > Player SettingsからApi Compatibility Levelを.NET 4.xに変更してみてください。

(現在の最新のUnityではApi Compatibility Levelが.NET Standard 2.0でもHttpClientを使用できます) f:id:dasuko:20200510184023p:plain

まとめ

HttpClientはかなり低レベルなAPIが揃っており、とても便利です。

それを全て紹介しようと思うと、かなりの量の記事になってしまうので

その他のAPIについては別の記事でまとめようかと思います。

  

何かご意見ありましたら気軽にコメントしてください。

 

この記事が参考になったという方や、不明点がある方、

ここ、間違っているよ!という方!気軽にコメントしてください!

 

 

Unityを本気で極めたい人は本を買ってもいいかも!

※本気じゃない人は買わないでください。

参考

docs.microsoft.com