AI対戦サーバープログラム作成のヒント/タイムアウト
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
[[AI対戦サーバープログラム作成のヒント]]
*その5 タイムアウトと入力検知 [#n191b74e]
5回目となる今回は、1入力に時間制限をつけるタイムアウト...
パイプにデータが入っているかを確認する入力検知を学びます。
まず入力検知が必要なのか? から始めていきます。
**入力検知の必要性 [#k6e8e222]
ReadFile関数はscanf関数やfgets関数と同じく、入力があるま...
プログラムが停止しているということは、他に何も行動が出来...
これを防ぐために、パイプやバッファ領域に読み取れるデータ...
***検知関数 [#t4d6db69]
では、パイプの中身を確認するにはどうしたらよいでしょうか。~
WinAPIでは、PeekNamedPipe関数が存在しますので、これを使い...
この関数は、パイプの中身のあるなしに関わらず、即座に制御...
ですので、この関数を繰り返し入力があったときだけReadFile...
**作るプログラム [#b8b50b98]
今回は、前回のプログラムを少し拡張するだけにします。
具体的には、以下の要素を追加します。~
-子プロセスにわざとタイムアウトさせる
-親プロセスは1回のやり取りに時間制限を持たせる
-時間切れになったら、そのプロセスは強制終了する
**子プロセスを作成する [#l81bdb86]
まず、子プロセスとなるプログラムを作ります。~
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int input();
int main() {
int l=0;
clocck_t start, end;
fprintf(stderr, "child start.\n");
while(l<10) {
int d = input();
start = clock();
do { end = clock(); }while(end - start < l*2000)
printf("%d\n", d*10);
fflush(stdout);
l++;
}
fprintf(stderr, "child end.\n");
return 0;
}
int input() {
char buf[16];
int d;
if(fgets(buf, 16-1, stdin) == NULL){
fprintf(stderr, "C:fgets return NULL\n");
exit(1);
}
d = atoi(buf);
return d;
}
前回のプログラムとほぼ同じです。~
異なる部分は、clock関数を追加して無駄に時間を使っているく...
clock関数はtime.hに含まれていますので、これをインクルード...
これをコンパイルして出来た実行ファイルを「child.exe」とし...
**親プロセスを作成する [#z35cc812]
親プロセスとなるプログラムを作成していきます。~
プログラムはやはり前回とほぼ同じ、違うのは、execute関数の...
***execute関数の後半部分 [#fa490628]
while(loop<5) {
int d = (loop+3)*2;
sprintf(str, "%d\n", d);
if(!WriteFile(stdinPipe[W], str, strlen(str), &numbe...
fprintf(stderr, "WriteFile\n");
return -1;
}
printf("P:send child(%d)\n", d);
start = clock();
do {
if(!PeekNamedPipe(stdoutPipe[R], NULL, 0, NULL, &n...
fprintf(stderr, "PeekNamedPipe\n");
return -1;
}
if(numberOfBytesRead > 0) break;
end =clock();
}while(end - start < 5000);
printf("wait time:%dms\n", end-start);
if(end - start >= 5000) break;
if(!ReadFile(stdoutPipe[R], buf, sizeof(buf)-1, &num...
if (GetLastError() == ERROR_BROKEN_PIPE) {
printf("broken pipe.\n");
break;
}else
fprintf(stderr, "ReadFile\n");
}
buf[numberOfBytesRead] = '\0';
printf("P:recieve:%s", buf);
loop++;
}
if(!TerminateProcess(childProcess, 0)) {
fprintf(stderr, "TerminateProcess(chileProcess)\n");
return -1;
}
if(!CloseHandle(stdoutPipe[R])) {
fprintf(stderr, "CloseHandle(stdoutPipe[R])\n");
return -1;
}
stdoutPipe[R] = NULL;
if(!CloseHandle(stdinPipe[W])) {
fprintf(stderr, "CloseHandle(stdinPipe[W])\n");
return -1;
}
stdinPipe[W] = NULL;
return 0;
}
パイプの確認をdo~whileループで回しています。~
入力が制限時間以内なら読み取り、オーバーなら処理ループを...
(外側のwhileから抜けると子プロセスは強制終了される)
**実行結果 [#f949fae0]
最後にこのプログラムの実行結果を確認しましょう。
2つの実行ファイルを同じフォルダに入れて親側のプログラムを...
parent start.
P:send child(6)
child start.
wait time:15ms
P:recieve:60
P:send child(8)
wait time:2000ms
P:recieve:80
P:send child(10)
wait time:4000ms
P:recieve:100
P:send child(12)
wait time:5000ms
parent end.
応答に5000ms以上かかった場合には、子プロセスから値を受け...
**補足 [#v7d9056b]
**次回 [#l78a28b0]
これで一通りのパイプに関する説明は終わりです。~
あとは実際にどうやって運用するのか、などを実例を持って説...
前回:[[その4 複数回通信と強制終了>AI対戦サーバープログ...
次回:まとめ・AIのクライアントを作ってみる?
*コメント [#wbac215c]
#comment
終了行:
[[AI対戦サーバープログラム作成のヒント]]
*その5 タイムアウトと入力検知 [#n191b74e]
5回目となる今回は、1入力に時間制限をつけるタイムアウト...
パイプにデータが入っているかを確認する入力検知を学びます。
まず入力検知が必要なのか? から始めていきます。
**入力検知の必要性 [#k6e8e222]
ReadFile関数はscanf関数やfgets関数と同じく、入力があるま...
プログラムが停止しているということは、他に何も行動が出来...
これを防ぐために、パイプやバッファ領域に読み取れるデータ...
***検知関数 [#t4d6db69]
では、パイプの中身を確認するにはどうしたらよいでしょうか。~
WinAPIでは、PeekNamedPipe関数が存在しますので、これを使い...
この関数は、パイプの中身のあるなしに関わらず、即座に制御...
ですので、この関数を繰り返し入力があったときだけReadFile...
**作るプログラム [#b8b50b98]
今回は、前回のプログラムを少し拡張するだけにします。
具体的には、以下の要素を追加します。~
-子プロセスにわざとタイムアウトさせる
-親プロセスは1回のやり取りに時間制限を持たせる
-時間切れになったら、そのプロセスは強制終了する
**子プロセスを作成する [#l81bdb86]
まず、子プロセスとなるプログラムを作ります。~
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int input();
int main() {
int l=0;
clocck_t start, end;
fprintf(stderr, "child start.\n");
while(l<10) {
int d = input();
start = clock();
do { end = clock(); }while(end - start < l*2000)
printf("%d\n", d*10);
fflush(stdout);
l++;
}
fprintf(stderr, "child end.\n");
return 0;
}
int input() {
char buf[16];
int d;
if(fgets(buf, 16-1, stdin) == NULL){
fprintf(stderr, "C:fgets return NULL\n");
exit(1);
}
d = atoi(buf);
return d;
}
前回のプログラムとほぼ同じです。~
異なる部分は、clock関数を追加して無駄に時間を使っているく...
clock関数はtime.hに含まれていますので、これをインクルード...
これをコンパイルして出来た実行ファイルを「child.exe」とし...
**親プロセスを作成する [#z35cc812]
親プロセスとなるプログラムを作成していきます。~
プログラムはやはり前回とほぼ同じ、違うのは、execute関数の...
***execute関数の後半部分 [#fa490628]
while(loop<5) {
int d = (loop+3)*2;
sprintf(str, "%d\n", d);
if(!WriteFile(stdinPipe[W], str, strlen(str), &numbe...
fprintf(stderr, "WriteFile\n");
return -1;
}
printf("P:send child(%d)\n", d);
start = clock();
do {
if(!PeekNamedPipe(stdoutPipe[R], NULL, 0, NULL, &n...
fprintf(stderr, "PeekNamedPipe\n");
return -1;
}
if(numberOfBytesRead > 0) break;
end =clock();
}while(end - start < 5000);
printf("wait time:%dms\n", end-start);
if(end - start >= 5000) break;
if(!ReadFile(stdoutPipe[R], buf, sizeof(buf)-1, &num...
if (GetLastError() == ERROR_BROKEN_PIPE) {
printf("broken pipe.\n");
break;
}else
fprintf(stderr, "ReadFile\n");
}
buf[numberOfBytesRead] = '\0';
printf("P:recieve:%s", buf);
loop++;
}
if(!TerminateProcess(childProcess, 0)) {
fprintf(stderr, "TerminateProcess(chileProcess)\n");
return -1;
}
if(!CloseHandle(stdoutPipe[R])) {
fprintf(stderr, "CloseHandle(stdoutPipe[R])\n");
return -1;
}
stdoutPipe[R] = NULL;
if(!CloseHandle(stdinPipe[W])) {
fprintf(stderr, "CloseHandle(stdinPipe[W])\n");
return -1;
}
stdinPipe[W] = NULL;
return 0;
}
パイプの確認をdo~whileループで回しています。~
入力が制限時間以内なら読み取り、オーバーなら処理ループを...
(外側のwhileから抜けると子プロセスは強制終了される)
**実行結果 [#f949fae0]
最後にこのプログラムの実行結果を確認しましょう。
2つの実行ファイルを同じフォルダに入れて親側のプログラムを...
parent start.
P:send child(6)
child start.
wait time:15ms
P:recieve:60
P:send child(8)
wait time:2000ms
P:recieve:80
P:send child(10)
wait time:4000ms
P:recieve:100
P:send child(12)
wait time:5000ms
parent end.
応答に5000ms以上かかった場合には、子プロセスから値を受け...
**補足 [#v7d9056b]
**次回 [#l78a28b0]
これで一通りのパイプに関する説明は終わりです。~
あとは実際にどうやって運用するのか、などを実例を持って説...
前回:[[その4 複数回通信と強制終了>AI対戦サーバープログ...
次回:まとめ・AIのクライアントを作ってみる?
*コメント [#wbac215c]
#comment
ページ名: