Hi,im a beginner using Elixir to write a chatroom project, and I've been stuck on setting up the connection between client and server. My plan is to write 2 modules for client and server and had them apply all their functions within their individual module. From the client side, its no more than setting up the socket connection and other send/receive functions from gen_tcp. For the server I implemented a handle_client function after accpeted connection to new client, and take the first message as username and connection signal. Here's the code:
# send welcome message to affirm connection, loop handler to listean and broadcast user's input
defp handle_client(socket) do
send_message(socket, "Welcome to the chat room!\nPlease enter your username: ")
Logger.info("handle_client: on listen client 1")
# successfully receive, other case err message
case recv(socket) do
{:ok, username} ->
Logger.info("#{username} joined the chat")
broadcast_message("#{username} joined the chat")
Logger.info("handle_client: on listen to client 2")
# keep listening to user input
loop(socket, username)
{:error} ->
Logger.info("Disconnected from the client")
end
end
Notice here that I warpped the recv/2 from gen_tcp to a custom recv/1, technically they do the samething except in case of error, I only return the atom {:error} instead of captureing the whole err message. Here if it's a successful return, then it will recognize the username and open the thread to that client.
Here's a little bit into the recv/1:
defp recv(socket) do
Logger.info("recv: on listen to client 1")
case :gen_tcp.recv(socket, 0) do
{:ok, data} -> {:ok, String.trim(data)}
///not included///Logger.info("recv: message as #{data} [case :ok]")
{:error, _reason} -> {:error}
///not included///Logger.info("recv: message as #{_reason} [case :error]")
end
Logger.info("recv: on listen to client 2")
end
Edit: sorry about the confusion but these debug lines are neither the actual bug nor included in the actual code.
You may ignore the debug log I added between, the way it perform is just as similar to recv/2. Here if I enter the username message from client, it will pass it into {:ok, data} and return to the case...do part in handle_client/1.
Here goes the problem: I tried to run the code and even if it successfully captured the username message, a CaseClauseError still occurs in the handle_client/1 where it says no matching for :ok
iex(2)>
05:58:28.083 [error] Process #PID<0.152.0> raised an exception
** (CaseClauseError) no case clause matching: :ok
(chatroom 0.1.0) lib/chat_server.ex:37: ChatServer.handle_client/1
Which is very confusing cause technically I think it should be passing the correct tuple instead of a single :ok atom, where I actually have the message correctly captured: debug log
Please tell me if you have any clue to the possible reason of it, and I will sincerely appreciate your help. If you think more information is needed I have very happy to discuss with you under the comment.
[wait what is this, I think I've included all the stuff above?]