Thomas
Thomas

Reputation: 357

OCaml websocket "Invalid UTF8 data"

I am trying to build a loop with Lwt that will push a frame to a Websocket, wait for the response, print it to the screen, wait 60 seconds and then repeat the process again. I have been able to get something that compiles but I do not have it 100% right yet. The first time through the loop everything works fine, then every time after that I receive the error message "Invalid UTF8 data". I must have something wrong in my Lwt loop or in my understanding of Websocket protocols. My code:

#require "websocket";;
#require "lwt";;
#require "lwt.syntax";;

open Lwt

(* Set up the websocket uri address *)
let ws_addr = Uri.of_string "websocket_address"

(* Set up the websocket connection *)
let ws_conn = Websocket.open_connection ws_addr

(* Set up a frame *)
let ws_frame = Websocket.Frame.of_string "json_string_to_server"

(* push function *)
let push frame () =
  ws_conn 
  >>= fun (_, ws_pushfun) ->
    ws_pushfun (Some frame);
    Lwt.return ()

(* get stream element and print to screen *)
let get_element () = 
  let print_reply (x : Websocket.Frame.t) = 
    let s = Websocket.Frame.content x in
    Lwt_io.print s; Lwt_io.flush Lwt_io.stdout;
  in
  ws_conn
  >>= fun(ws_stream, _) ->
      Lwt_stream.next ws_stream
      >>= print_reply 

let rec main () =
  Lwt_unix.sleep 60.0
  >>= (push ws_frame)
  >>= get_element
  >>= main

Lwt_main.run(main ())

Upvotes: 3

Views: 337

Answers (1)

ivg
ivg

Reputation: 35280

I'm not sure what particularly incorrect with your code. It even doesn't compiles on my system. It looks like you were experimenting with it in a top-level and created some strange context. I've rewritten your code in a somewhat more cleaner way. First of all I pass a connection to the function, so that it is more cleaner, what your functions do. Also it is not a good idea to wait for the same thread again and again. This is not how things are done is Lwt.

open Lwt

(* Set up the websocket uri address *)
let ws_addr = Uri.of_string "websocket_address"

(* Set up a frame *)
let ws_frame = Websocket.Frame.of_string "json_string_to_server"

(* push function *)
let push (_,push) frame  =
  push (Some frame);
  return_unit


(* get stream element and print to screen *)
let get_element (stream,_) =
  let print_reply (x : Websocket.Frame.t) =
    let s = Websocket.Frame.content x in
    Lwt_io.printlf "%s%!" s in
    Lwt_stream.next stream
    >>= print_reply

let rec main conn : unit t =
  Lwt_unix.sleep 60.0
  >>= fun () -> push conn ws_frame
  >>= fun () -> get_element conn
  >>= fun () -> main conn

let () = Lwt_main.run (
    Websocket.open_connection ws_addr >>= main)

Upvotes: 1

Related Questions