I'm trying to write an IRC inspired server along with a client capable of communicating with it as a part of my uni class. I already wrote a server with which i can successfully interact using tools such as telnet. I'm having trouble with writing a client though, specifically with sending messages from stdin to the server. Module that i use for sending/receiving messages looks as follows:
let (>>=) = Lwt.bind
type t =
{ user_input : Lwt_io.input_channel;
server_input : Lwt_io.input_channel;
output : Lwt_io.output_channel }
let make fd =
{ user_input = Lwt_io.stdin;
server_input = Lwt_io.of_fd ~mode:Lwt_io.input fd;
output = Lwt_io.of_fd ~mode:Lwt_io.output fd }
let send conn msg =
Lwt_io.write conn.output msg >>= fun _ ->
Lwt_io.flush conn.output
let receive input_ch =
Lwt_io.read_line input_ch
>>= fun line ->
Lwt.return line
Funny enough, i know that it almost works properly thanks to some classic print_endline
debugging techniques (I logged messages sent and received by the server). The problem is, when i type something in my terminal, it doesn't go through to the server until i press ctrl+c
. Example session looks as follows:
ctrl+c
in my client sessionctrl+c
Based on that i assume the message doesn't actually get sent through the socket until i press ctrl+c
for some unknown reason.
server responses and corresponding client session for some more reference
I was wondering if it can somehow be caused by the way i read lines using Lwt_io.read_line
, something about it maybe not recognizing newline characters and how to fix that (So it works as intended, that is sending typed message to the server after pressing Enter
). Additionally here's the code responsible for the main loop of the client:
let rec handle_user conn () =
let open Connection in
receive conn.user_input
>>= fun msg ->
send conn msg
>>= handle_user conn
let rec handle_server conn () =
let open Connection in
receive conn.server_input
>>= fun msg ->
Lwt_io.write Lwt_io.stdout msg
>>= handle_server conn
let handle_connection conn () =
Lwt.join [
handle_user conn ();
handle_server conn ()
]
handle_connection conn ()
is launched from the main function using Lwt_main.run
after doing some standard stuff on sockets. I feel like I have scoured half of the Internet trying to come up with a solution and yet I couldn't find anything and it completely blocks my further progress working on the project.
TL:DR
Tried: Sending a message to the server after typing it in my client session and pressing Enter
What i expected: Response from the server signaling that it in fact received a message along with it's content
What actually happened: The message didn't go through until closing the client with ctrl+c
after which the server signaled receiving all messages typed so far but glued together, ignoring newline characters
As far as I can see (without any way to reproduce the error), the issue is that Lwt_io.read_line
returns the line without the newline characters as documented at https://ocsigen.org/lwt/5.5.0/api/Lwt_io#VALread_line. Thus,
receive conn.user_input
>>= send conn
does not send any newlines, and the server has no way to know that the current message ended before the end of the connection.