2

I am attempting to write a simple test case exercising MsgReceive(), MsgSend(), and MsgReply() but I feel like I am fundamentally misunderstanding how these functions work. Here is my attempt:

printf("Testing MsgReceive()...\n");
printf("Receives message and place it into a buffer.\n");
chid = ChannelCreate(_NTO_CHF_SENDER_LEN);
if(chid == -1){
    printf("ChannelCreate FAILED!");
}
coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0);
pid = fork();
if(pid == -1){
    return;
}
            
if(pid == 0){
    msgSend = MsgSend(coid, writemsg, 13, buffer, 13);
    if(msgSend == -1){
        printf("Child FAILED: %d\n", msgSend);
    }
}
else{
    msgRec = MsgReceive(chid, buffer, 13, NULL);
    printf("Sent Message: %s\n", buffer);
    if(msgRec == -1){
        printf("Parent FAILED: %d\n", msgRec);
    }
}
if(pid == 0){
    if(ChannelDestroy(chid) == -1){
        printf("ChannelDestroy() failed.\n");
    }
}

I create a channel and then connect the process to the channel. I fork and have the child send the message and the parent receive it. But I can never get the child to send. It always fails.

2 Answers2

-1

You are doing a couple of things wrong.

  1. The second parameter of ConnectAttach, process_id is the process_id of the owner of the channel. In this case, the parent process. So, my suggestion is to use this process_id in the ConnectAttach call.

  2. ConnectAttach should be called in the child process.

This is what should be done.

Server process:

  1. Calls ChannelCreate and then stores process_id and channel_id in a file
  2. MsgReceive (blocking call), MsgReply

Client process:

  1. Calls ConnectAttach with the process_id, and channel_id obtained from the file that the server stored this info in.
  2. Calls ConnectAttach which returns a connection_id
  3. Calls MsgSend with the connection_id from step 2.
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
-3
#include <stdio.h>
#include <stdlib.h> /* for EXIT_FAILURE */
#include <errno.h> /* for EOK */
#include <sys/neutrino.h>

#define RECV_BUFLEN 255

int
main (void)
{
    int recv_id;
    int channel_id;
    char recv_msg[RECV_BUFLEN];
    char reply_msg[255];
    char send_msg[255];
    int reply_length;
    int send_length;
    pid_t this_pid;
    pid_t child_pid;
    int recv_i;
    int reply_i;
    int conn_id;

    this_pid = getpid ();

    /* Set up a channel through which client (the child process) can connect to me. */
    channel_id = ChannelCreate (0);
    if (channel_id == -1) {
      fprintf (stderr, "server: ERROR: Couldn't create a channel\n");
      return (EXIT_FAILURE);
    }
    printf ("Server process id = %d, channel id = %d\n", this_pid, channel_id);

    printf ("parent process id = %d\n", this_pid);
    printf ("Channel id = %d\n", channel_id);
    printf ("Press CTRL-C to quit.\n");

    child_pid = fork();
    if (child_pid == -1) {
        perror("fork");
    } else if (child_pid == 0) {
        /* child process */
        conn_id = ConnectAttach(0, this_pid, channel_id, 0, 0);
        printf( "Child connecting to process %d, channel %d\n",
                       this_pid, channel_id );
        if (conn_id == -1) {
            fprintf( stderr, "client: ERROR: Can't connect\n" );
            exit( EXIT_FAILURE );
        }
    do {
        printf("Enter a message to send (empty string quits) :" );
        strcpy( send_msg, "" );
        scanf( "%[^\n]%*c", send_msg );
        printf( "\n" );

        if ( strlen( send_msg ) > 0 ) {
            /* Add one to the length to include the NULL terminator byte. */
            send_length = strlen( send_msg ) + 1;

            /* Tell the user what's happening */
            printf( "Child Sending message {%s}\n", send_msg );

            /* This function will block until the message is received.  Ensure that it
             * is not a problem for the app to be blocked, or that the server always
             * replies soon enough to avoid problems, or both. */
            MsgSend( conn_id, send_msg, send_length, recv_msg, RECV_BUFLEN );

            /* Surround the received reply with braces to show that it has been
               * terminated properly. */
               printf( "Reply received = {%s}\n", recv_msg );
        }   /* User did enter something */

      } while ( strlen( send_msg ) > 0 ); /* Quit if nothing to send */
   } else {
       /* parent process */
       /* Keep running indefinitely. */
       while (1) {
           /* Block until a message is ready for me on the specified channel.
            *  * Store the ID of the client, so I can reply to it uniquely.
            */
           recv_id = MsgReceive (channel_id, recv_msg, RECV_BUFLEN, NULL);
           printf ("Parent Received ID = {%d}, message = {%s}\n", recv_id,
                    recv_msg);
           /* Pause long enough to show the Photon client app being blocked. */
           printf ("Processing reveived message, please wait...\n");
           sleep (2);

           /* Make a reply by reversing the sent message (don't include the null
            *        * byte terminator ) */
           reply_i = strlen (recv_msg) - 1;
           for (recv_i = 0; recv_i < strlen (recv_msg); recv_i++)

           {
               reply_msg[reply_i] = recv_msg[recv_i];
               reply_i--;
           }

           /* NULL-terminate the reversed string */
           reply_msg[strlen (recv_msg)] = '\0';

           /* Add one to the message length to include the NULL terminator byte. */
           reply_length = strlen (reply_msg) + 1;

           /* Surround the messge with curly braces to indicate that the string
            *        * has been terminated properly. */
           printf ("Parent Replying with message = {%s}\n", reply_msg);

           /* Send a reply to the client specified by the receive ID. */
           MsgReply (recv_id, EOK, reply_msg, reply_length);
       }                                /* while true */
       return;
   }
}
  • 2
    Welcome to Stack Overflow. Code is a lot more helpful when it is accompanied by an explanation. Stack Overflow is about learning, not providing snippets to blindly copy and paste. Please [edit] your answer and explain how it answers the specific question being asked. See [answer]. – ChrisGPT was on strike Jun 18 '22 at 16:38