uv_write how is the uv_stream_t created for client

335 views
Skip to first unread message

Darrel Cusey

unread,
Jul 29, 2015, 3:10:14 PM7/29/15
to libuv
Soooo close...

I have successfully started a pipe listener using the code shown below.  Now in a separate process, I want to connect the that same pipe and send a message -- but I don't see any documentation on how to define the required uv_stream_t in this scenario.  All the examples assume that only the server writes to the pipe (by using the "client" steam from the connect).

Here's my server code, which works fine:

#if _WIN32 || _WIN64
const char *pipename = "\\\\.\\pipe\\my.pipe";
#else
cosnt char *pipename = "my.pipe";
#endif


void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
    if (nread < 0) {
        if (nread != UV_EOF)
            fprintf(stderr, "Read error %s\n", uv_err_name(nread));
        uv_close((uv_handle_t*) client, NULL);
        return;
    }

    fprintf(stdout, "Received message: %s\n", buf->base);
    free(buf->base);
}

void on_new_connection(uv_stream_t *server, int status) {
    if (status == -1) {
        // error!
        return;
    }

    uv_pipe_t *client = (uv_pipe_t*) malloc(sizeof(uv_pipe_t));
    uv_pipe_init(loop, client, 0);
    if (uv_accept(server, (uv_stream_t*) client) == 0) {
        uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
    }
    else {
        uv_close((uv_handle_t*) client, NULL);
    }
}


void main {

  loop = uv_default_loop();

  uv_pipe_t server;
  uv_pipe_init(loop, &server, 0);

  signal(SIGINT, remove_sock);

char *args[3];
  char *y = new char[processPath.length()+1];
  std::strcpy(y, processPath.c_str());
  char pidBuffer[19];
  itoa(getProcessID(), pidBuffer, 10);
  args[0] = y;
  args[1] = pidBuffer;
args[2] = NULL;


  // startup the listener
  fprintf(stdout, "Starting Listener...\n");
  int q;
  if ((q = uv_pipe_bind(&server, pipename))) {
      fprintf(stderr, "Bind error %s\n", uv_err_name(q));
      return false;
  }
  if ((q = uv_listen((uv_stream_t*) &server, 16, on_new_connection))) {
      fprintf(stderr, "Listen error %s\n", uv_err_name(q));
      return false;
  }


return (uv_run(loop, UV_RUN_DEFAULT) == 0);
}




Now, on the client, I want to connect to this pipe and send a message -- but can't figure out how to define the uv_stream_t value.. 


#if _WIN32 || _WIN64
const char *pipename = "\\\\.\\pipe\\my.pipe";
#else
cosnt char *pipename = "my.pipe";
#endif


main {


uv_pipe_t* handle = (uv_pipe_t*)malloc(sizeof(uv_pipe_t));
uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));

uv_pipe_init(uv_default_loop(), handle, 0);
uv_pipe_open(handle, socket(PF_UNIX, SOCK_STREAM, 0));

int r;
uv_pipe_connect(connect, handle, pipename, OnConnect);

// send a message to the pipe



uv_stream_t steam; // <---- How do I define this ????



uv_write_t *req = (uv_write_t *) malloc(sizeof(uv_write_t));
uv_buf_t wrbuf = uv_buf_init("123456789\n", 10);
uv_write(req, stream, &wrbuf, 1, echo_write);


uv_run(uv_default_loop(), UV_RUN_DEFAULT);

}



Can anyone point me in the right direction, I think I'm really close to solving this (????)





Saúl Ibarra Corretgé

unread,
Jul 29, 2015, 4:29:13 PM7/29/15
to li...@googlegroups.com
Hi!
You might want to pass 'free' as the callback so the handle's memory is
released.

> }
> }
>
>
> void main {
>
> loop = uv_default_loop();
>
> uv_pipe_t server;
> uv_pipe_init(loop, &server, 0);
>
> signal(SIGINT, remove_sock);

You could use a uv_signal_t handle here.
You don't need to do uv_pipe_open, that's for using an *existing* fd as
a pipe. Just call uv_pipe_init and then do the uv_pipe_connect.

> // send a message to the pipe
>
>
>
> uv_stream_t steam; // <---- How do I define this ????
>

uv_pipe_t is a "subclass" of uv_stream_t
(http://docs.libuv.org/en/v1.x/pipe.html#uv-pipe-t-pipe-handle), you can
just cast it to uv_stream_t. All these funcions work on streams, so you
just need to cast the handle: http://docs.libuv.org/en/v1.x/stream.html

>
>
> uv_write_t *req = (uv_write_t *) malloc(sizeof(uv_write_t));
> uv_buf_t wrbuf = uv_buf_init("123456789\n", 10);
> uv_write(req, stream, &wrbuf, 1, echo_write);
>
>
> uv_run(uv_default_loop(), UV_RUN_DEFAULT);
>
> }
>
> |
>
>
> Can anyone point me in the right direction, I think I'm really close to
> solving this (????)
>

Hope that helps!


Cheers,

--
Saúl Ibarra Corretgé
http://bettercallsaghul.com

Darrel Cusey

unread,
Jul 29, 2015, 5:08:18 PM7/29/15
to libuv, sag...@gmail.com
Thank you so much!  That worked perfectly :D

Brian Hamon

unread,
Jul 29, 2015, 5:46:36 PM7/29/15
to li...@googlegroups.com
You can just cast the handle in the callback req to a uv_stream_t*. Yes, that handle is actually a uv_pipe_t*, but libuv takes that into account. Here's a fully tested implementation of your client program:

#include <uv.h>
#include <stdlib.h>
#include <stdio.h>

#if _WIN32 || _WIN64
const char *pipename = "\\\\.\\pipe\\my.pipe";
#else
const char *pipename = "my.pipe";
#endif

static void close_cb(uv_handle_t* handle) {
    free(handle);
}

void echo_write(uv_write_t* req, int status) {
    if (status != 0) {
        printf("%s: %s %s\n", __func__, uv_err_name(status), uv_strerror(status));
    } else {
        uv_close((uv_handle_t*)req->handle, close_cb);
    }
    free(req);
}

void OnConnect(uv_connect_t* in_req, int status) {
    if (status != 0) {
        printf("%s: %s %s\n", __func__, uv_err_name(status), uv_strerror(status));
    } else {
        // send a message to the pipe

        uv_write_t *out_req = (uv_write_t *) malloc(sizeof(uv_write_t));
        uv_buf_t wrbuf = uv_buf_init("123456789\n", 10);
        uv_write(out_req, (uv_stream_t*)in_req->handle, &wrbuf, 1, echo_write);
    }
    free(in_req);
}

int main() {
        uv_pipe_t* handle = (uv_pipe_t*)malloc(sizeof(uv_pipe_t));
        uv_connect_t* connect = (uv_connect_t*)malloc(sizeof(uv_connect_t));

        uv_pipe_init(uv_default_loop(), handle, 0);
        uv_pipe_open(handle, socket(PF_UNIX, SOCK_STREAM, 0));

        uv_pipe_connect(connect, handle, pipename, OnConnect);

        return uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}


--
You received this message because you are subscribed to the Google Groups "libuv" group.
To unsubscribe from this group and stop receiving emails from it, send an email to libuv+un...@googlegroups.com.
To post to this group, send email to li...@googlegroups.com.
Visit this group at http://groups.google.com/group/libuv.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages