Chat server: Difference between revisions

Content added Content deleted
(Added Prolog Implementation)
Line 2,097: Line 2,097:
| Connection closed.
| Connection closed.
| $</pre>
| $</pre>

=={{header|Prolog}}==
Works with Swi-Prolog as of Jan 2019.

This version will load the server automatically on port 5000, adapt to your needs.
<lang prolog>:- initialization chat_server(5000).

chat_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, _),
thread_create(process_client(Socket, _), _, [detached(true)]),
dispatch(AcceptFd).

process_client(Socket, _) :-
setup_call_cleanup(
tcp_open_socket(Socket, Str),
handle_connection(Str),
close(Str)).

% a connection was made, get the username and add the streams so the
% client can be broadcast to.
handle_connection(Str) :-
send_msg(Str, msg_welcome, []),
read_line_to_string(Str, Name),
send_msg(Str, msg_welcome_name, Name),
connect_user(Name, Str), !.

% connections are stored here
:- dynamic(connected/2).

connect_user(Name, Str) :-
connected(Name, _),
send_msg(Str, msg_username_taken, []).
connect_user(Name, Str) :-
\+ connected(Name, _),
% make sure that the connection is removed when the client leaves.
setup_call_cleanup(
assert(connected(Name, Str)),
(
broadcast(Name, msg_joined, Name),
chat_loop(Name, Str), !,
broadcast(Name, msg_left, Name)
),
retractall(connected(Name, _))
).

% wait for a line to be sent then broadcast to the rest of the clients
% finish this goal when the client disconnects (end of stream)
chat_loop(Name, Str) :-
read_line_to_string(Str, S),
dif(S, end_of_file),
broadcast(Name, msg_by_user, [Name, S]),
chat_loop(Name, Str).
chat_loop(_, Str) :- at_end_of_stream(Str).

% send a message to all connected clients except Name (the sender)
broadcast(Name, Msg, Params) :-
forall(
(connected(N, Str), dif(N, Name)),
(send_msg(Str, Msg, Params), send_msg(Str, msg_new_line, []))
).

send_msg(St, MsgConst, Params) :-
call(MsgConst, Msg),
format(St, Msg, Params),
flush_output(St).

% constants for the various message types that are sent
msg_welcome('Welcome to Chatalot\n\rPlease Enter your nickname: ').
msg_welcome_name('Welcome ~p\n\r').
msg_joined(' -- "~w" has joined the chat --').
msg_left(' -- "~w" has left the chat. --').
msg_username_taken('That username is already taken\n\r').
msg_new_line('\n\r').
msg_by_user('~w> ~w').</lang>


=={{header|Python}}==
=={{header|Python}}==