2

I wrote a client and server for tests. Client:

static Soup.WebsocketConnection websocket;

int main (string[] args)
{
    var ws_session = new Soup.Session();
    var ws_message = new Soup.Message("GET", "http://127.0.0.1:8088/");

    string[] protocols = {"chat"};
    var ws_loop = new MainLoop();
    ws_session.websocket_connect_async.begin(ws_message, "localhost", protocols, null, (obj, res) => {
        websocket = ws_session.websocket_connect_async.end(res);
        websocket.message.connect(rec_message);
    });
    ws_loop.run();

    stdout.printf("Program end. Press ENTER"); // the program does not reach this point
    stdin.read_line();
    websocket.close(0, null);
    return 0;
}

void rec_message(int type, Bytes message){
    stdout.printf("WebSock receive:\n");
    stdout.printf("%s\n".printf((string)message.get_data()));
    websocket.send_text("test_message2"); // client does not send message
}

And server:

public class WSServer : Soup.Server {
    private int access_counter = 0;
    public WSServer(){
        assert (this != null);
        string[] protocols = {"chat"};
        this.add_websocket_handler(null,"localhost", protocols, get_ws);
    }

    void get_ws(Soup.Server server, Soup.WebsocketConnection connection, string path, Soup.ClientContext client){
        connection.message.connect(ws_message);
        string host = client.get_host();
        info (@"Client connected! Host: $host");
        string msg = """test_message1""";
        info (@"Sending to client message: $msg");
        connection.send_text(msg);
    }

    void ws_message(int id, Bytes msg){
        string message = (string)msg.get_data();
        info(@"Message received! ID: $id Message:\n$message\n");
    }
}

int main (string[] args)
{
    try {
        int port = 8088;
        MainLoop loop = new MainLoop ();
        WSServer server = new WSServer ();
        server.listen_local (port, 0);
        loop.run ();
    } catch (Error e) {
        error ("Error: %s\n", e.message);
    }

    stdout.printf("Programm end. Press ENTER");
    stdin.read_line ();
    return 0;
}

After starting the server and client, the connection and exchange of the first message occurs test_message1 after which the server closes the connection and no longer receives messages. The client attempts to send a message test_message2 and then closes the connection with the code and the error message: WS Error 44: Error receiving data: Connection reset by peer

Syabro
  • 65
  • 7
  • Once you have the connection established you probably want to [`steal_connection`](https://valadoc.org/libsoup-2.4/Soup.ClientContext.steal_connection.html) to get the `IOStream`. Then you can use [`DataInputStream`](https://valadoc.org/gio-2.0/GLib.DataInputStream.html) and [`DataOutputStream`](https://valadoc.org/gio-2.0/GLib.DataOutputStream.html) to conveniently communicate over the connection. This [Valum code](https://github.com/valum-framework/valum/blob/master/src/valum-websocket.vala) may be a good starting point – AlThomas Feb 29 '20 at 21:56
  • @AlThomas I use Soup to configure, maintain and process streams. It has a WebsocketConnection class that provides message receiving signals and sending functions. – Syabro Feb 29 '20 at 22:04
  • I assume your using https://valadoc.org/libsoup-2.4/Soup.Session.websocket_connect_async.html? – Zander Brown Mar 01 '20 at 00:53
  • @AlexB yes i added an example – Syabro Mar 01 '20 at 09:32
  • That example isn't complete (where is rec_message?) and you almost certainly don't want to call `loop.quit();` there, your quitting the program just after opening a connection – Zander Brown Mar 01 '20 at 21:54
  • @AlexB What is the difference actually in `rec_message`? There is just a message output. I don’t know what you meant by speaking of `loop.quit()`, but that pushed me to a solution. `MainLoop`, as in the analogy with `Soup.Server`, must be running all the time the `websocket` connection is running. – Syabro Mar 02 '20 at 05:34
  • Well the difference is that something is wrong and I can't build incomplete code – Zander Brown Mar 02 '20 at 15:42
  • What I mean by `loop.quit()` is that your calling in right there in that snippet and you shouldn't, like you say the loop needs to be running for the connection to work (otherwise the program just quits) – Zander Brown Mar 02 '20 at 15:43
  • @AlexB in the function that interests you, I just output to the console `(string)Bytes.get_data()`. – Syabro Mar 02 '20 at 16:08
  • I doesn't really interest me, it's that it makes it a lot easier to help when you provide a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) – Zander Brown Mar 02 '20 at 17:00
  • @AlexB ok, sorry, i'll fix it soon – Syabro Mar 02 '20 at 22:04

1 Answers1

2

In general, the solutions to my questions are as follows:

  1. The first problem was solved by removing ws_loop.quit();:
var ws_loop = new MainLoop();
ws_session.websocket_connect_async.begin(ws_message, "localhost", protocols, null, (obj, res) => {
    websocket = ws_session.websocket_connect_async.end(res);
    websocket.message.connect(rec_message);
    //ws_loop.quit(); // this error
});
ws_loop.run();
  1. The connection is closed by the server since the instance WebsocketConnection is destroyed when exiting the function void get_ws(Soup.Server server, Soup.WebsocketConnection connection, string path, Soup.ClientContext client)
Syabro
  • 65
  • 7