2012-12-17 45 views
2

因此,我目前處於構建遊戲的初始階段,並且我正在使用prolog作爲遊戲的服務器端來對板中的遊戲進行驗證檢查。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),但我的服務器沒有按」 t關閉...它接收到end_of_file,它會打印end_of_file,但它不會關閉。甚至沒有將其直接插入到服務器中。我究竟做錯了什麼?

二:我需要從C++傳遞一個字符串到Swipl,它具有要使用的謂詞的名稱和參數。有人可以告訴我如何做到這一點,或至少指出我在正確的方向嗎?

非常感謝。

回答

1

一:你可以解決一個簡單的方法或複雜的方式。簡單的方法是重新啓動不僅僅是你的服務器,而且是Prolog解釋器。複雜的是在接收到「關閉」消息時調用一個乾淨地退出程序的謂詞。

二:讀/ 2謂詞,它將參數作爲輸入流(在這種情況下,您的套接字的讀取結束)和一個將被放置分析輸入的變量,只是您想要的:讀取一個來自輸入的術語,並將其轉換爲它代表的Prolog術語,就好像您已將其寫入Prolog程序一樣。請注意,在該術語之後,輸入必須包含一個點以告訴Prolog該術語已經結束(如另一個答案所示)。

+0

好吧,據我所知,處理給定連接的線程正常關閉。會發生什麼是我似乎無法遠程關閉main_thread ......也許我們不應該能夠這樣做。無論如何,感謝您的幫助。 :) – Sidner

2

不應該Int == end_of_fileInt = 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 
+0

可能是,但它在客戶端工作,應該在服務器端工作。就第二個問題而言,我會在Swi中嘗試。謝謝。 =) – Sidner