Розетки в Swipl

Итак, я сейчас на начальной стадии построения игры и использую пролог в качестве серверной части игры для проверки правильности игр на игровом поле.

У меня сейчас две проблемы.

Один:
Невозможно закрыть сервер без прерывания и, таким образом, оставить сокет открытым.
Код выглядит следующим образом

Сервер:

:- 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, которая содержит имя предиката для использования и аргументы. Может кто-нибудь сказать мне, как это сделать, или, по крайней мере, указать мне правильное направление?

Большое спасибо.

2

Решение

Один: вы можете решить это простым или сложным способом. Простой способ — перезапустить не только ваш сервер, но и интерпретатор Prolog. Сложным является вызов предиката, который корректно выходит из программы при получении сообщения «close».

Два: предикат read / 2, который принимает в качестве параметров входной поток (в данном случае конец чтения вашего сокета) и переменную, в которую будет помещен проанализированный вход, выполняет то, что вы хотите: он читает термин из input и преобразует его в термин Prolog, который он представляет, как если бы вы написали его в программе Prolog. Обратите внимание, что после термина ввод должен содержать точку, чтобы сообщить Прологу, что термин закончился (как показывает другой ответ).

1

Другие решения

не должны Int == end_of_file быть Int = end_of_file, чтобы проверить объединение? Я могу ошибаться здесь, я использую sicstus.

Что касается того, как передать имя предиката и аргументы, что-то вроде этого должно работать

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

Тогда в С ++ просто делай

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

Пролог преобразует входящую строку в реальный код, если вы скажете это.
Альтернативная, более общая реализация

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

и в C ++

write(socket, "[myPredicate, Arg1, Arg2, Arg3].\n");
//supports variable number of args
3

По вопросам рекламы [email protected]