Remote message-passing example

bridged with qdn.public.qnxrtp.applications
Post Reply
Ramon Sarrate

Remote message-passing example

Post by Ramon Sarrate » Thu May 23, 2002 6:15 pm

Hi,

I am looking for an example which shows how I can send a message from a
client thread on a local machine to a server thread on a remote machine
over QNET.

After reading the QNX documentation I've learned the following:

* The Server has to use ChannelCreate(), MsgReceive() and MsgReply()
* The Client has to use ConnectAttach() and MsgSend()

I've successfully managed to communicate two threads in the same node,
but I don't know how to connecte remote nodes.

In ConnectAttach() I should specify the ND, the PID and the CHID. But,
since the communicating processes are remote how can I know the remote
PID and CHID?. As far as I know both parameters are specified at
run-time and I do not have a shared memory between them!!!!.

So, an example could help.

Thank you,

Ramon

Robert Krten

Re: Remote message-passing example

Post by Robert Krten » Thu May 23, 2002 6:15 pm

Ramon Sarrate <sarrate@esaii.upc.es> wrote:
Hi,

I am looking for an example which shows how I can send a message from a
client thread on a local machine to a server thread on a remote machine
over QNET.
open ("/net/magenta/dev/ser1", O_RDONLY);
After reading the QNX documentation I've learned the following:

* The Server has to use ChannelCreate(), MsgReceive() and MsgReply()
* The Client has to use ConnectAttach() and MsgSend()

I've successfully managed to communicate two threads in the same node,
but I don't know how to connecte remote nodes.
It's much easier to use "open()" instead of ConnectAttach(); the file
descriptor you get *is* a connection ID :-)
In ConnectAttach() I should specify the ND, the PID and the CHID. But,
since the communicating processes are remote how can I know the remote
PID and CHID?. As far as I know both parameters are specified at
run-time and I do not have a shared memory between them!!!!.

So, an example could help.

Thank you,

Ramon
--
Robert Krten, PARSE Software Devices +1 613 599 8316.
Realtime Systems Architecture, Books, Video-based and Instructor-led
Training and Consulting at www.parse.com.
Email my initials at parse dot com.

Xiaodan Tang

Re: Remote message-passing example

Post by Xiaodan Tang » Fri May 24, 2002 12:13 am

Ramon Sarrate <sarrate@esaii.upc.es> wrote:
Hi,

I've successfully managed to communicate two threads in the same node,
but I don't know how to connecte remote nodes.

In ConnectAttach() I should specify the ND, the PID and the CHID. But,
since the communicating processes are remote how can I know the remote
PID and CHID?. As far as I know both parameters are specified at
run-time and I do not have a shared memory between them!!!!.
Now, how do you ConnectAttach() in local case? How do you get
those "local pid, chid" ?

Well, you memtioned "shared memory", so I guess you are write that
into a shared memory area, right ? But if you can write to shared
memory, you can also write it into a file say /var/run/serverchannel,
and let the client open and read it out. The same "remote" case,
is to open /net/remote/var/run/serverchannel, and ConnectAttach() to
it.

But yes, you realize this break the whole purpose of IPC. That is,
2 process have to rely on 3rd party (be it the manager of shared memory,
or the manager of /var/run/serverchannel).

The solution of this is use "name space", that is, the server would
associated it's nd/pid/chid with a "name". Thus, a client simply ask
to connect to, say, "/dev/myserver", and got the connection. The name_*()
functions servers that purpose.

More further, you server may want to suppose those POSIX operation,
open/read/write/close/... Instead of attach a name, look each message
the client send to you and figure out what he want, you server could
use "resource manager" library, which, all these "standard message"
will be covered, and you only prepare functions like "open_handler()",
"read_handler()", "write_handler()" ...

And that is the final solution for remote case.
open("/net/remote/dev/myserver", O_RDONLY), the client will got a fd
to read/write to, and the server, will have it's "open_handler()"
get called. Both side do not need any special code to handle
"network case".

-xtang

Ramon Sarrate

Re: Remote message-passing example

Post by Ramon Sarrate » Mon May 27, 2002 11:16 am

Thanks Xiaodan,

As you mention fisrt option (file-based) is no satisfactory.

Second option would be nice (but QNX docs say named_* functions are not
recommended for QNX 6 version)

Third option sounds me complex.

I would really like to illustrate to students how easily they can communicate
to remote threads via message-passing.

I have attached the sample code that I've written to check message-passing
communication between two threads of the same process. I would like to
transform this into two applications, one run on a local node and the other
in a remote node. So I would like to check message-passing communication
between two threads on remote nodes.

It would be nice if I you or someone else could provide this code.

thanks in advance,

Ramon



Xiaodan Tang wrote:
Ramon Sarrate <sarrate@esaii.upc.es> wrote:
Hi,

I've successfully managed to communicate two threads in the same node,
but I don't know how to connecte remote nodes.

In ConnectAttach() I should specify the ND, the PID and the CHID. But,
since the communicating processes are remote how can I know the remote
PID and CHID?. As far as I know both parameters are specified at
run-time and I do not have a shared memory between them!!!!.

Now, how do you ConnectAttach() in local case? How do you get
those "local pid, chid" ?

Well, you memtioned "shared memory", so I guess you are write that
into a shared memory area, right ? But if you can write to shared
memory, you can also write it into a file say /var/run/serverchannel,
and let the client open and read it out. The same "remote" case,
is to open /net/remote/var/run/serverchannel, and ConnectAttach() to
it.

But yes, you realize this break the whole purpose of IPC. That is,
2 process have to rely on 3rd party (be it the manager of shared memory,
or the manager of /var/run/serverchannel).

The solution of this is use "name space", that is, the server would
associated it's nd/pid/chid with a "name". Thus, a client simply ask
to connect to, say, "/dev/myserver", and got the connection. The name_*()
functions servers that purpose.

More further, you server may want to suppose those POSIX operation,
open/read/write/close/... Instead of attach a name, look each message
the client send to you and figure out what he want, you server could
use "resource manager" library, which, all these "standard message"
will be covered, and you only prepare functions like "open_handler()",
"read_handler()", "write_handler()" ...

And that is the final solution for remote case.
open("/net/remote/dev/myserver", O_RDONLY), the client will got a fd
to read/write to, and the server, will have it's "open_handler()"
get called. Both side do not need any special code to handle
"network case".

-xtang

Stepan Hejny

Re: Remote message-passing example

Post by Stepan Hejny » Mon May 27, 2002 2:53 pm

hi,

will be NAME_FLAG_ATTACH_GLOBAL supported for name_* functions ?
it's unsupported for a long time now ^^

stepan


"Xiaodan Tang" <xtang@qnx.com> pí¹e v diskusním pøíspìvku
news:ack0is$7o3$1@nntp.qnx.com...
Ramon Sarrate <sarrate@esaii.upc.es> wrote:
Hi,

I've successfully managed to communicate two threads in the same node,
but I don't know how to connecte remote nodes.

In ConnectAttach() I should specify the ND, the PID and the CHID. But,
since the communicating processes are remote how can I know the remote
PID and CHID?. As far as I know both parameters are specified at
run-time and I do not have a shared memory between them!!!!.

Now, how do you ConnectAttach() in local case? How do you get
those "local pid, chid" ?

Well, you memtioned "shared memory", so I guess you are write that
into a shared memory area, right ? But if you can write to shared
memory, you can also write it into a file say /var/run/serverchannel,
and let the client open and read it out. The same "remote" case,
is to open /net/remote/var/run/serverchannel, and ConnectAttach() to
it.

But yes, you realize this break the whole purpose of IPC. That is,
2 process have to rely on 3rd party (be it the manager of shared memory,
or the manager of /var/run/serverchannel).

The solution of this is use "name space", that is, the server would
associated it's nd/pid/chid with a "name". Thus, a client simply ask
to connect to, say, "/dev/myserver", and got the connection. The name_*()
functions servers that purpose.

More further, you server may want to suppose those POSIX operation,
open/read/write/close/... Instead of attach a name, look each message
the client send to you and figure out what he want, you server could
use "resource manager" library, which, all these "standard message"
will be covered, and you only prepare functions like "open_handler()",
"read_handler()", "write_handler()" ...

And that is the final solution for remote case.
open("/net/remote/dev/myserver", O_RDONLY), the client will got a fd
to read/write to, and the server, will have it's "open_handler()"
get called. Both side do not need any special code to handle
"network case".

-xtang

Xiaodan Tang

Re: Remote message-passing example

Post by Xiaodan Tang » Mon May 27, 2002 3:32 pm

Stepan Hejny <Stepan.Hejny@aveco.com> wrote:
hi,

will be NAME_FLAG_ATTACH_GLOBAL supported for name_* functions ?
it's unsupported for a long time now ^^
It is supported in name_attach(), but is not supported in
name_open() function.

I am reposting my "gname_open()" function below, it works arround
the problem and give you connection to a GLOBAL attached name.

-xtang

----------------------- cut here --------------------------------
#include <sys/dispatch.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <share.h>

int gname_open(const char *name, int flags)
{
int fd;
DIR *dir;
struct dirent *dent;
char *newname;

if ((fd = name_open(name, flags)) != -1 || (flags & NAME_FLAG_ATTACH_GLOBAL) == 0) {
return fd;
}

if ((dir = opendir("/net")) == NULL) {
errno = ENOENT;
return -1;
}

while (dent = readdir(dir)) {
newname = alloca(strlen("/net/") + strlen(dent->d_name) +
strlen("/dev/name/global/") + strlen(name) + 1);
if (!newname) {
errno = ENOMEM;
return -1;
}
sprintf(newname, "/net/%s/dev/name/global/%s", dent->d_name, name);
fd = _connect(_NTO_SIDE_CHANNEL, newname, 0, O_RDWR, SH_DENYNO,
_IO_CONNECT_OPEN, 1, _IO_FLAG_RD | _IO_FLAG_WR,
_FTYPE_NAME, 0, 0, 0, 0, 0, 0);
if (fd != -1) {
closedir(dir);
return fd;
}
}

closedir(dir);
errno = ENOENT;
return -1;
}

Stepan Hejny

Re: Remote message-passing example

Post by Stepan Hejny » Tue May 28, 2002 7:43 am

thank you


"Xiaodan Tang" <xtang@qnx.com> pí¹e v diskusním pøíspìvku
news:actjhq$9ak$4@nntp.qnx.com...
Stepan Hejny <Stepan.Hejny@aveco.com> wrote:
hi,

will be NAME_FLAG_ATTACH_GLOBAL supported for name_* functions ?
it's unsupported for a long time now ^^

It is supported in name_attach(), but is not supported in
name_open() function.

I am reposting my "gname_open()" function below, it works arround
the problem and give you connection to a GLOBAL attached name.

-xtang

----------------------- cut here --------------------------------
#include <sys/dispatch.h
#include <dirent.h
#include <errno.h
#include <fcntl.h
#include <share.h

int gname_open(const char *name, int flags)
{
int fd;
DIR *dir;
struct dirent *dent;
char *newname;

if ((fd = name_open(name, flags)) != -1 || (flags &
NAME_FLAG_ATTACH_GLOBAL) == 0) {
return fd;
}

if ((dir = opendir("/net")) == NULL) {
errno = ENOENT;
return -1;
}

while (dent = readdir(dir)) {
newname = alloca(strlen("/net/") + strlen(dent->d_name) +
strlen("/dev/name/global/") + strlen(name) + 1);
if (!newname) {
errno = ENOMEM;
return -1;
}
sprintf(newname, "/net/%s/dev/name/global/%s", dent->d_name,
name);
fd = _connect(_NTO_SIDE_CHANNEL, newname, 0, O_RDWR, SH_DENYNO,
_IO_CONNECT_OPEN, 1, _IO_FLAG_RD | _IO_FLAG_WR,
_FTYPE_NAME, 0, 0, 0, 0, 0, 0);
if (fd != -1) {
closedir(dir);
return fd;
}
}

closedir(dir);
errno = ENOENT;
return -1;
}

Post Reply

Return to “qdn.public.qnxrtp.applications”