2

所以我目前正处于构建游戏的开始阶段,我正在使用 prolog 作为游戏的服务器端来对棋盘中的游戏进行验证检查。

我目前有两个问题。

一:似乎无法在不中止的情况下关闭服务器,从而使套接字保持打开状态。代码如下

服务器:

:- 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 但它没有关闭。即使将其直接插入服务器也不行。我究竟做错了什么?

二:我需要将一个字符串从 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

一:你可以用简单的方法或复杂的方法来解决这个问题。简单的方法是不仅重新启动您的服务器,还重新启动 Prolog 解释器。复杂的是调用一个谓词,当收到“关闭”消息时干净地退出程序。

二:read/2 谓词,它以输入流(在本例中为套接字的读取端)和一个变量作为参数,解析后的输入将被放置在其中,它只是你想要的:它从输入并将其转换为它所代表的 Prolog 术语,就像您在 Prolog 程序中编写它一样。请注意,在术语之后,输入必须包含一个点来告诉 Prolog 术语已经结束(如另一个答案所示)。

于 2012-12-17T18:01:58.970 回答