2

私は現在、ゲーム構築の開始段階にあり、ゲームのサーバー側としてプロローグを使用して、ボードでのプレイの検証チェックを行っています。

現在2つの問題を抱えています。

1: 中止せずにサーバーを閉じることができないように見えるため、ソケットを開いたままにします。コードは次のとおりです

サーバ:

:- use_module(library(socket)).


create_server(Port) :-
        tcp_socket(Socket),
        tcp_bind(Socket, Port),
        tcp_listen(Socket, 5),
        tcp_open_socket(Socket, AcceptFd, _),
    dispatch(AcceptFd).

dispatch(AcceptFd) :-
        tcp_accept(AcceptFd, Socket, Peer),
        thread_create(process_client(Socket, Peer), _,
                      [ detached(true)
                      ]),
        dispatch(AcceptFd).

process_client(Socket, _Peer) :-
        setup_call_cleanup(tcp_open_socket(Socket, In, Out),
                           handle_service(In, Out),
                           close_connection(In, Out)).

close_connection(In, Out) :-
        close(In, [force(true)]),
        close(Out, [force(true)]).

handle_service(In, Out) :-
    read(In, Int),
    writeln(Int),
    (   Int == end_of_file
    ->  true
    ;   
        call_test(Int,Term),
        format(Out, 'seen(~q).~n', [Term]),
        flush_output(Out),
        handle_service(In, Out)
    ).

call_test(test,Term):-Term = 'really test'.
call_test(validate(teste),Term):-
    String = "validate(test)",
    string_to_list(String,List),
    read_from_chars(List,Stringf),
    writeln(Stringf), 
    Term = 'foo'.

クライアント:

:- use_module(library(streampool)).

create_client(Host, Port) :-
        setup_call_catcher_cleanup(tcp_socket(Socket),
                                   tcp_connect(Socket, Host:Port),
                                   exception(_),
                                   tcp_close_socket(Socket)),
        setup_call_cleanup(tcp_open_socket(Socket, In, Out),
                           chat_to_server(In, Out),
                           close_connection(In, Out)).

chat_to_server(In, Out) :-
        read(Term),
    (   Term == end_of_file
    ->  true
    ;   format(Out, '~q .~n', [Term]),
        flush_output(Out),
        read(In, Reply),
        write(Reply),
        %format('Reply: ~q.~n', [Reply]),
        chat_to_server(In, Out)
    ).

close_connection(In, Out) :-
        close(In, [force(true)]),
        close(Out, [force(true)]).

ctrl+D (end_of_file) を使用して問題なくクライアントを閉じることができますが、サーバーが閉じません... end_of_file を受け取り、end_of_file を出力しますが、閉じません。サーバーに直接挿入する場合でも。私は何を間違っていますか?

2: 使用する述語の名前と引数を含む文字列を C++ から Swipl に渡す必要があります。誰かがこれを行う方法を教えてください。または、少なくとも正しい方向に向けてください。

どうもありがとうございました。

4

2 に答える 2

3

統一を確認するために、Int == end_of_fileすべきではありませんか? Int = end_of_fileここで間違っているかもしれません。私はsicstusを使用しています。

述語名と引数を渡す方法については、次のようなものが機能するはずです

call_test(Request, Answer) :-
    Request = Pred(Arg1, Arg2, Arg3),
    Request,
    Answer = somethingHere.

次に、C++で単純に実行します

//pseudo-code
write(socket, "myPredicate(myArg1, myArg2, myArg3).\n");

Prolog は、指示があれば、入力文字列を実際のコードに変換します。代替の、より一般的な実装は次のとおりです。

call_test(Request, Answer) :-
    Pred =.. Request,
    Pred,
    Answer = somethingHere.

そしてC++で

write(socket, "[myPredicate, Arg1, Arg2, Arg3].\n");
//supports variable number of args
于 2012-12-17T15:52:08.610 に答える
1

1: 簡単な方法または複雑な方法で解決できます。簡単な方法は、サーバーだけでなく Prolog インタープリターも再起動することです。複雑なのは、「クローズ」メッセージを受信したときにプログラムを完全に終了する述語を呼び出すことです。

2: read/2 述語は、入力ストリーム (この場合はソケットの読み取り側) と、解析された入力が配置される変数をパラメーターとして取り、必要なことを行います。入力し、Prolog プログラムで記述したかのように、それが表す Prolog 用語に変換します。用語の後に、入力にドットを含めて、用語が終了したことを Prolog に伝える必要があることに注意してください (他の回答が示すように)。

于 2012-12-17T18:01:58.970 に答える