3

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 ())
Thomas
  • 347
  • 3
  • 19

1 Answers1

1

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)
ivg
  • 34,431
  • 2
  • 35
  • 63
  • I tried your code and I run into the same issue. I get a result the first time and then after the first run of main I receive "Invalid UTF8 data" errors. I have tried my version and your version on multiple websockets to make sure it was not an issue with a particular server. (Note: I had to remove the type signature in your code for it to compile.) – Thomas Oct 02 '14 at 00:50
  • Ok, then it looks like, that the problem is not in your code. Maybe the implementation is not full. I would suggest you to experiment with the example program from the websocket library https://github.com/vbmithr/ocaml-websocket/blob/master/tests/wscat.ml – ivg Oct 02 '14 at 01:36
  • there're server and client implementations, you can start a server and check, whether it can communicate with your client. Next, you can use their client to talk to your server, etc. – ivg Oct 02 '14 at 01:37