James Bridson <james@socrates.demon.co.uk> wrote:
Hi,
I am trying to implement a basic QNX message passing system between
different machines in a QNX native network (Qnet). So far I have
configured the machines for both qnet and ttcpip and both seem to
be working fine. I can use tcp services between hosts and I also
see the /net/ entries for all the active nodes. I am using
dns to resolve the Qnet hosts and not ndp.
Next I tried to write a simple client-server process pair to try
out various things with the message passing interfaces and Qnet
in general so I implemented a simple server process that does a
‘name_open()’ on a global name ‘testname’ and a client that uses
‘name_attach()’ to attach to it. The name appears ok in /dev/global
on the node running the server and if I run the client on the same
node it also works fine. However I was under the impression that
Qnet would let me run the client on a node other than the server
node and the name resolving would take place automatically by
virtue of using the GLOBAL flags when I create/attach the name.
Can anyone help me here? The manual pages I have (developer CD
for RTP beta) are rather limited and I cannot find any relevant
FAQs on the net. Is what I am doing wrong or am I missing some
form of configuration? Should I be able to see the global names
over the whole Qnet?
I THINK propagation of global names is not yet supported. Try using
a resource manager for your name location and open the path accross
the network.
That is, have the resource manager attach a name like “/myname”,
and the client do a ‘open ("/qnet/node/myname", …)’ and MsgSend()
to that filedescriptor.
Here is a sample resource manager that attaches a name, and handles
messages where the first 16-bits (short int) have the value of
IO_MAX+1 (that is 512).
-David
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/neutrino.h>
#include <sys/dispatch.h>
#include <sys/iofunc.h>
struct msg { unsigned short type;
unsigned short subtype;
char data[256];
}
int message_handler( message_context_t *ctp, int code, unsigned flags,
void *handle );
/* several structures that need to exist, but we will only initialize */
resmgr_connect_funcs_t connect_fn;
resmgr_io_funcs_t io_fn;
iofunc_attr_t attr;
resmgr_attr_t resmgr_attr;
int main()
{
dispatch_t *dpp;
dispatch_context_t *ctp;
int id;
/* create a dispatch structure, contents are hidden */
dpp = dispatch_create();
/* initialize the default io functions. In a resource manager
we would overwrite some of these */
iofunc_func_init( _RESMGR_CONNECT_NFUNCS, &connect_fn, _RESMGR_IO_NFUNCS,
&io_fn );
/* initialize the attributes structure */
iofunc_attr_init( &attr, S_IFNAM|0666, 0, 0 );
/* make sure the default buffer is large enough for our message */
resmgr_attr.msg_max_size = sizeof( struct msg );
/* attach our name */
id = resmgr_attach( dpp, &resmgr_attr, “/myname”, _FTYPE_ANY, 0,
&connect_fn, &io_fn, &attr );
printf(“resmgr_attach returned %d, errno %d:’%’\n”, id, errno,
strerror(errno) );
/* attach a handler for a private message of type IO_MAX+1 /
message_attach( dpp, 0, IO_MAX+1, IO_MAX+1, message_handler, NULL );
/ will see some of the contents of the ctp in the callbacks */
ctp = dispatch_context_alloc( dpp );
/* loop forever /
for(; {
ctp = dispatch_block( ctp ); / wait for a message /
printf(“got a message\n”);
printf(“type is %d\n”, ctp->resmgr_context.msg->msg.i.type );
dispatch_handler( ctp ); / handle the message */
}
}
/* the message handler function */
int message_handler( message_context_t *ctp, int code, unsigned flags,
void *handle )
{
struct msg *my_msg;
/* print out the contents of the message and reply /
/ the message is defined in “resmgr.h”, and includes a data field. /
/ the message is available as ctp->msg */
my_msg = (struct msg *) ctp->msg;
printf(“resmgr: got message ‘%s’\n”, my_msg->data );
MsgReply( ctp->rcvid, 0, “Hi there”, 9 );
return 0;
}
-David