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}}== |