2019年2月22日金曜日

サイズの大きいデータをPOSTすると404エラーが発生する

ASP.NETで作成したWeb APIに対し、HttpClientを使用して、JSONデータをPOSTするコードを書きました。

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Clear();
    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

    var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
    var task= client.PostAsync(uri, content).ContinueWith(x =>
    {
        var response = x.Result;
        if (!response.IsSuccessStatusCode)
        {
            throw new Exception(response.ReasonPhrase);
        }

        ・・・
    });
    try
    {
        task.Wait();
    }
    catch (AggregateException ex)
    {
        throw ex.Flatten();
    }
    catch
    {
        throw;
    }
}

40MB近くあるデータをPOSTしたところ、レスポンスに「Not Found」、いわゆる404エラーが返ってきました。












送信データサイズが小さい場合は問題はなく、エラーの原因がサイズの大きさにあることは明らかなのですが、
サーバーが受け取るリクエストの最大サイズはmaxRequestLengthですでに指定しています。
調べてみると、どうやらそれだけでは不十分で、リクエスト内のコンテンツ最大長(maxAllowedContentLength)の指定も
必要だということが分かりました。
web.configにmaxAllowedContentLengthを追加し、送信データサイズ以上の値を指定すると、エラーが返ることはなくなりました。

  <system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="52428800"></requestLimits>
      </requestFiltering>
    </security>
  </system.webServer>

またいつか、どこかで。

2019年2月15日金曜日

TeraTermマクロで自動接続 & マクロ毎に設定ファイルを切り替える!



こんにちは。よっしーです。

皆さん TeraTerm 使ってますか?


Linuxや仮想マシンを使っていると、

リモート接続する際に TeraTerm をよく使います。


で、複数台にリモート接続する場合、

TeraTermを複数立ち上げるワケですが、

どの画面がどのリモート接続か、

見分けがつかなくなることがあります。

(↓こんな感じ)


で、これを回避するため、

コンソール毎に背景色を変えたりするわけですが、

(↓色が違うと見分けも付きやすい!!)


1つずつ手動で色の変更を行うのは面倒なので、

私はTeraTermの設定ファイルをいくつか用意し、

自動接続マクロにその設定ファイルを指定するような方法で

TeraTermの切り分けをしています。


以下、マクロの例です。

(↓赤枠でTeraTerm設定ファイルを指定しています。


マクロファイルをttl拡張子で保存し、TeraTermから関連付けすると、

ダブルクリックだけで自動的にリモート接続し、対象の設定ファイルが

適応された状態でTeraTermが立ち上がります。


設定ファイルには、色の他にも、ログ出力の設定だったり、

いろいろとカスタマイズできる項目があるので、

「接続先によって設定を切り替えたい!」とお困りの方は、お試し下さい。


ではまた~。

2019年2月11日月曜日

メモリのセクション内の配置を確認してみた

こんにちは、ふじかーです。

前回書いた.bssセクションのグローバル変数の初期化についての記事、
組み込み屋さんには当たり前の事と言われるかもしれませんが
本当にそうなってるか気になったので、実際に動かして確認してみました。


セクション概要


プログラムはメモリに配置されて実行されるわけですが
メモリ上にはプログラム内の「機械語」や「変数」「定数」など、各種用途に分けて配置され

その単位のことをセクションといいます。


と、ここまでは前回記載しましたが、

これ以外にもプログラム実行中、関数内のローカル変数等が
使用されるときに配置される「スタック領域」がありますね。

上記のセクション は
 プログラムをコンパイル(リンク)した時点でアドレスとサイズが決まり、
 実行中に変わる事はない、静的な領域
なのに対し、

スタック領域 は
 プログラム実行中、使用時に一時的に確保されたり開放されたりする、
 動的な領域
という違いがあります。


テストプログラム


それらを確認するため
変数の値や配置アドレスを出力するだけのプログラムを書いてみます。

#include <stdio.h>
int global_int1 = 111;   //global 初期値あり
int global_int2;   //global 初期値なし
int global_int3 = 0;   //global 初期値0
const char global_chr1[] = "abc"; //global constあり
      char global_chr2[] = "def"; //global constなし

int section_test(int param);

int main(void)
{
    int ret = 0;
    ret = section_test(123);
    return 0;
}

int section_test(int param)
{
    int local_int1 = 222;  //local 初期値あり
    int local_int2;   //local 初期値なし
    int local_int3 = 0;   //local 初期値0
    static int local_int4 = 333; //local static 初期値あり
    static int local_int5;  //local static 初期値なし
    static int local_int6 = 0;  //local static 初期値0

    printf("\n■関数\n");
    printf("main()          (0x%X)\n", &main);
    printf("section_test()  (0x%X)\n", &section_test);
    
    printf("\n■引数\n");
    printf("param   (0x%X) = %d \n", &param , param);
    
    printf("\n■グローバル変数\n");
    printf("global_int1 初期値あり (0x%X) = %d \n", &global_int1 , global_int1);
    printf("global_int2 初期値なし (0x%X) = %d \n", &global_int2 , global_int2);
    printf("global_int3 初期値0    (0x%X) = %d \n", &global_int3 , global_int3);
    printf("global_chr1 constあり  (0x%X) = %s \n", &global_chr1 , global_chr1);
    printf("global_chr2 constなし  (0x%X) = %s \n", &global_chr2 , global_chr2);

    printf("\n■ローカル変数\n");
    printf("local_int1  初期値あり (0x%X) = %d \n", &local_int1 , local_int1);
    printf("local_int2  初期値なし (0x%X) = %d \n", &local_int2 , local_int2);
    printf("local_int3  初期値0    (0x%X) = %d \n", &local_int3 , local_int3);

    printf("\n■静的ローカル変数(static)\n");
    printf("local_int4  初期値あり (0x%X) = %d \n", &local_int4 , local_int4);
    printf("local_int5  初期値なし (0x%X) = %d \n", &local_int5 , local_int5);
    printf("local_int6  初期値0    (0x%X) = %d \n", &local_int6 , local_int6);

    return 0;
}


各種変数をprintf出力するだけなのに、意外と長くなってしまいました
これを例によってVS Codeでコンパイルして、動かしてみます。


実行結果が




また、前回同様 objdump で実行ファイルの内容を確認しておきます。




メモリ配置確認


さて、実際の配置はどうなっているでしょうか。
テストプログラムでの実行結果を絵にすると、こんな感じになりました。


各変数は、想定したセクションに置かれていました


・・・とまぁ結果としては大体想定通り動いているようです。

「ほぉ、確かにこんな風に配置されるんだな」

とイメージ出来ていると、もしかしたら
いずれ業務で会話に出たとき役に立ったりするかもしれません。
プログラム初心者の方は参考にしてください。

※ここまで書いて、せっかくだったら「ヒープ領域」も
 追加しときゃよかったかな・・・とも思いましたが、
 まぁ想像以上にゴチャゴチャしてきたし、今回はここまでとします。。

2019年2月3日日曜日

秀丸grepをフォルダの右クリックメニューから行う



こんにちは。よっしーです。

仕事柄、テキストエディタとして秀丸エディタをよく使います。


秀丸にはgrep機能があり、

ソースコードを追いかける場合などは必須の機能となります。


で、grepをする場合、秀丸の検索メニューから

「grepの実行」を行うことになるのですが、

当然ながら「秀丸を起動」する必要があり、

これが手順として面倒な場合があります。


・プログラムから秀丸を起動

 (ここがダメ)grep時にgrep対象のフォルダパスを指定しなければならない


・秀丸に関連付けされたファイルを選択して秀丸を起動

 (ここがダメ)grep対象が開いたファイルのカレントフォルダとなっているので、
        異なるフォルダをgrepしたい場合はパスを指定しなおさなければならない

 (ここがダメ)わざわざ秀丸に関連付いたファイルを探し出して選択しないといけない





で、私はこの面倒を解決するため、

フォルダの右クリックメニューに「秀丸grep」という処理を追加しています。




これをするためには、レジストリエディタでレジストリを手修正する必要があります。


やり方としては以下です。

(1) HKEY_CLASSES_ROOT\Folder\shell の下に、キー追加。
  わかりやすい名前をつけます。私は「秀丸grep」としています。

(2) 作成した「秀丸grep」の下に、キー追加。
  「command」という名前にして下さい。

(3) 「command」の(規定)というデータに、以下を設定。
  "C:\Program Files (x86)\Hidemaru\Hidemaru.exe" /d"%1" /g
  ※ 秀丸の実行ファイルパスは環境によって合わせて下さい。


これだけです。


これでフォルダを右クリックすることで、秀丸grepが選択できるようになり、

選択すると、右クリックしたフォルダパスが検索対象となった状態で

grep機能が立ち上がります。




まぁ、些細なもんですが、チリも積もれば日々の生産性も上がるということで、

興味があれば試してみてください。

ちなみに、これは秀丸だけではなく、サクラエディタ等でも同じように設定できます。


それでは~。