% Prolog communicator % author: Piotr Holownia % USTAL PORT! communicator_port(33777). %%% Commands: % msg(+User,+Msg). e.g. msg(peter,"Hello my dear!"). % who. - shows who is connected. % quit. - closes connection. :- use_module(library(socket)). :- dynamic user_streams/3. send_msg(Stream,Msg) :- write(Stream,Msg), write(Stream,'.'), nl(Stream), flush_output(Stream). %%%%%%%%%%%%% CLIENT %%%%%%%%%%%%% start_client(Name) :- tcp_socket(Socket), communicator_port(Port), tcp_connect(Socket,localhost:Port), tcp_open_socket(Socket,Read_stream,Write_stream), thread_create(read_server_message(Read_stream),_,[detached(true)]), send_msg(Write_stream,name(Name)), write_to_server(Write_stream), close(Read_stream), close(Write_stream). write_to_server(Write_stream) :- read(Cmd), send_msg(Write_stream,Cmd), write_to_server(Write_stream). read_server_message(Read_stream) :- read(Read_stream,Input), server_input(Input), read_server_message(Read_stream). % server msg command server_input(server_msg(List)) :- string_to_list(Msg,List), write('Server message: '),writeln(Msg). % msg command server_input(msg(Sender,List)) :- string_to_list(Msg,List), write('Message from '),write(Sender),write(': '),writeln(Msg). % quit command server_input(server_quit) :- writeln('Connection closed by server.'), assert(connection_closed), thread_exit('Connection closed'). % who command server_input(server_who(Users)) :- writeln('Users connected to the server:'), print_user(Users). print_user([]). print_user([User|Tail]) :- write(' - '),writeln(User), print_user(Tail). %%%%%%%%%%%%% SERVER %%%%%%%%%%%%% start_server :- tcp_socket(Socket), communicator_port(Port), tcp_bind(Socket,Port), tcp_listen(Socket,5), tcp_open_socket(Socket,_,_), writeln('Server running...'), wait_for_client(Socket). wait_for_client(Socket) :- tcp_accept(Socket,Slave,Peer), % Waiting for a connection. thread_create(dispatch(Slave,Peer),_,[detached(true)]), wait_for_client(Socket). dispatch(Slave,Peer) :- tcp_open_socket(Slave,Read_stream,Write_stream), read(Read_stream,name(Name)), assert(user_streams(Name,Read_stream,Write_stream)), write('Connection to user '),write(Name),write(' ('),write(Peer),writeln(') established.'), handle_client(Read_stream,Write_stream). handle_client(Read_stream,Write_stream) :- send_msg(Write_stream,server_msg("Hello! I am a communication server")), send_msg(Write_stream,server_msg("Type commands:")), read_client_message(Read_stream,Write_stream). read_client_message(Read_stream,Write_stream) :- read(Read_stream,Input), client_input(Read_stream,Write_stream,Input), read_client_message(Read_stream,Write_stream). % msg command client_input(_,Write_stream,msg(Addressee,Msg)) :- user_streams(Addressee,_,Stream), user_streams(Sender,_,Write_stream), send_msg(Stream,msg(Sender,Msg)). % quit command client_input(Read_stream,Write_stream,quit) :- send_msg(Write_stream,server_quit), close(Read_stream), close(Write_stream), retract(user_streams(Name,Read_stream,Write_stream)), write('Connection to user '),write(Name),writeln(' closed.'), thread_exit('Connection closed'). % who command client_input(_,Write_stream,who) :- setof(U,Y^Z^user_streams(U,Y,Z),Users), send_msg(Write_stream,server_who(Users)). % unknown command client_input(_,Write_stream,_) :- send_msg(Write_stream,server_msg("Unknown command!")).