所以我目前正处于构建游戏的起始阶段,我正在使用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的字符串,该字符串具有要使用的谓词的名称和参数。有人可以告诉我该怎么做或者至少指出我正确的方向吗?
非常感谢。
答案 0 :(得分:3)
Int == end_of_file
Int = end_of_file
不应该call_test(Request, Answer) :-
Request = Pred(Arg1, Arg2, Arg3),
Request,
Answer = somethingHere.
来检查统一?我可能在这里错了,我使用sicstus。
关于如何传递谓词名称和参数,这样的事情应该起作用
//pseudo-code
write(socket, "myPredicate(myArg1, myArg2, myArg3).\n");
然后在C ++中完成
call_test(Request, Answer) :-
Pred =.. Request,
Pred,
Answer = somethingHere.
如果您告诉它,Prolog会将传入的字符串转换为实际代码。 另一种更通用的实现是
write(socket, "[myPredicate, Arg1, Arg2, Arg3].\n");
//supports variable number of args
和C ++
{{1}}
答案 1 :(得分:1)
一:您可以通过简单的方式或复杂的方式解决这个问题。简单的方法是不仅重新启动服务器,还重启Prolog解释器。复杂的是在收到“关闭”消息时调用一个干净地退出程序的谓词。
二:read / 2谓词,它将输入流作为参数(在这种情况下是套接字的读取端)和一个将放入解析输入的变量,它可以满足您的需要:它读取一个来自输入的术语并将其转换为它所代表的Prolog术语,就像您在Prolog程序中编写它一样。请注意,在该术语之后,输入必须包含一个点,以告诉Prolog术语已结束(如另一个答案所示)。