Using tungstenite to create a WebSocket client

Hello, new to Rust.

I'm using the below code as a WebSocket client to query a WebSocket server for streaming data as it arrives.

use tungstenite::{connect, Message};
use url::Url;

fn main() {
    env_logger::init();

    let (mut socket, response) =
        connect(Url::parse("ws://public-node.test.dev:26657/websocket").unwrap()).expect("Can't connect");

    println!("Connected to the server");
    println!("Response HTTP code: {}", response.status());
    println!("Response contains the following headers:");
    for (ref header, _value) in response.headers() {
        println!("* {}", header);
    }

    socket.write_message(Message::Text("Hello, Test!".into())).unwrap();
    loop {
        let msg = socket.read_message().expect("Error reading message");
        println!("Received: {}", msg);
    }
    // socket.close(None);
}

However, all I'm receiving back are empty Received: messages.

test_ws git:master ❯ cargo run                                                 ✭
   Compiling anchor v0.1.0 (/Users/grokpronoia/rustTest/test_ws)
    Finished dev [unoptimized + debuginfo] target(s) in 1.22s
     Running `target/debug/test_ws`
Connected to the server
Response HTTP code: 101 Switching Protocols
Response contains the following headers:
* upgrade
* connection
* sec-websocket-accept
Received: {
  "jsonrpc": "2.0",
  "error": {
    "code": -32700,
    "message": "Parse error. Invalid JSON",
    "data": "error unmarshaling request: invalid character 'H' looking for beginning of value"
  }
}
Received:
Received:
Received:

My goal is to query the server and return the current (and historical) data so that I can parse it accordingly. What am I missing, i.e., how can i return the data on the WebSocket server to my client?

FWIW, I'm aware the socket.write_message(Message::Text("Hello, Test!".into())).unwrap(); is superfluous.

Thank you in advance for the help.

But that's exactly what's tripping your sever up. Look at the error message:

    "data": "error unmarshaling request: invalid character 'H' looking for beginning of value"

Apparently, your server expects some kind of JSON format. You send "Hello, Test!", which is not valid JSON. Valid JSON starts with a { or a [, not with H like "Hello".

Removing the line that contains socket.write_message(...) still results in receiving empty Received: messages.

My question should have been, how do you stream all new messages from a WebSocket server to a WebSocket client using tungstenite?

Looks like they're just empty ping messages. I tried your code out with https://www.websocket.org/echo.html and I was able to receive an echo. I would try to print out the debug representation of the messages you're getting to see what's going on in more detail.

-         println!("Received: {}", msg);
+         println!("Received: {:?}", msg);

Here's my output using Display ({})

Connected to the server
Response HTTP code: 101 Switching Protocols
Response contains the following headers:
* connection
* date
* sec-websocket-accept
* server
* upgrade
Received: Hello, Test!
Received: 

and with Debug ({:?})

Connected to the server
Response HTTP code: 101 Switching Protocols
Response contains the following headers:
* connection
* date
* sec-websocket-accept
* server
* upgrade
Received: Text("Hello, Test!")
Received: Ping([])

The Display impl of Message converts the contents of the Ping (Vec) into a String, in this case resulting in an empty string since the vec is empty.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.