Как получающий процесс фактически получает процесс от процесса отправителя через очереди сообщений? - PullRequest
0 голосов
/ 01 марта 2020

Я работаю над проектом с процессом отправителя и получателя, используя общую память и очередь сообщений. На всю жизнь я не могу заставить процесс получения получать файл, но я не могу понять, что на самом деле идет не так. Кажется, что он на самом деле не получает файл, или он просто застрял в бесконечном l oop.

Итак, я понимаю, что, используя очередь сообщений, вам необходимо присоединиться к очереди сообщений, используя идентификатор очереди сообщений. Затем, когда вы отправляете сообщение, оно отправляется в очередь сообщений, и получатель может получить его из этой очереди сообщений. Однако это то, что я делаю (я думаю) в своем коде, но, как уже упоминалось, процесс получателя, похоже, не получает файл. Так я ошибаюсь в том, как процесс получает сообщение и, следовательно, неправильно реализует код? Любая помощь будет принята с благодарностью, так как мой профессор просто бросил нас в это без объяснения того, как это сделать, поэтому я пытался учить себя. Вот что у меня есть для моего кода:

message.h:

#include <stdio.h>
/* The information type */

#define SENDER_DATA_TYPE 1

/* The done message */
#define RECV_DONE_TYPE 2

/**
 * The message structure
 */


struct message
{
        /* The message type */
        long mtype;

        /* How many bytes in the message */
        int size;

        /**
         * Prints the structure
         * @param fp - the file stream to print to
         */

        void print(FILE *fp)
        {
                fprintf(fp, "%ld %d", mtype, size);
        }
};

Отправитель. cpp:

#include <iostream>
#include <sys/shm.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "msg.h"    /* For the message struct */

/* The size of the shared memory chunk */
#define SHARED_MEMORY_CHUNK_SIZE 1000

/* The ids for the shared memory segment and the message queue */
 int shmid, msqid;

/* The pointer to the shared memory */
 void* sharedMemPtr;

/**
 * Sets up the shared memory segment and message queue
 * @param shmid - the id of the allocated shared memory
 * @param msqid - the id of the shared memory
 */

 void init(int& shmid, int& msqid, void*& sharedMemPtr)
{
        std::cout<<"Creating key"<<std::endl;
        key_t key = ftok("keyfile.txt", 'a');
        std::cout<<"Key created"<<std::endl;

        shmid =shmget(key,SHARED_MEMORY_CHUNK_SIZE, 0644|IPC_CREAT);
        std::cout<<"allocated shared memory"<<std::endl;

        sharedMemPtr = shmat(shmid,NULL,0);
        std::cout<<"Attached to shared memory"<<std::endl;

        msqid = msgget(key,0644|IPC_CREAT);
        std::cout<<"Attahed to message queue"<<std::endl;
}

 void cleanUp(const int& shmid, const int& msqid, void* sharedMemPtr)
{
        /* TODO: Detach from shared memory */
        shmdt(sharedMemPtr);
}

/**
 * The main send function
 * @param fileName - the name of the file
 */
void send(const char* fileName)
{
        /* Open the file for reading */
        FILE* fp = fopen(fileName, "r");

        /* A buffer to store message we will send to the receiver. */
        message sndMsg;

        /* A buffer to store message received from the receiver. */
        message rcvMsg;

        /* Was the file open? */
        if(!fp)
        {
                perror("fopen");
                exit(-1);
        }

        /* Read the whole file */
        while(!feof(fp))
        {
    if((sndMsg.size = fread(sharedMemPtr, sizeof(char), SHARED_MEMORY_CHUNK_SIZE, fp)) < 0)
                {
                        perror("fread");
                        exit(-1);
                }

                /* TODO: Send a message to the receiver telling him that the data is ready
                 * (message of type SENDER_DATA_TYPE)
                 */

                sndMsg.mtype = SENDER_DATA_TYPE;
                sndMsg.size = 0;
                msgsnd(msqid,&sndMsg,sizeof(sndMsg),0);
                std::cout<<"Sent data ready message"<<std::endl;
                /* TODO: Wait until the receiver sends us a message of type RECV_DONE_TYPE telling us
                 * that he finished saving the memory chunk.
                 */
                std::cout<<"Waiting for reciever message"<<std::endl;
                msgrcv(msqid,&rcvMsg,0,RECV_DONE_TYPE,0);
                std::cout<<"Message received"<<std::endl;
        }

       /** TODO: once we are out of the above loop, we have finished sending the file.
          * Lets tell the receiver that we have nothing more to send. We will do this by
          * sending a message of type SENDER_DATA_TYPE with size field set to 0.
          */
        sndMsg.size =0;
        sndMsg.mtype = SENDER_DATA_TYPE;
        std::cout<<"Sending empty message"<<std::endl;
        msgsnd(msqid,&sndMsg,sizeof(sndMsg),0);
        std::cout<<"Empty message sent"<<std::endl;
        /* Close the file */
        fclose(fp);

}

int main(int argc, char** argv)
{

        /* Check the command line arguments */
        if(argc < 2)
        {
                fprintf(stderr, "USAGE: %s <FILE NAME>\n", argv[0]);
                exit(-1);
        }

        /* Connect to shared memory and the message queue */
        init(shmid, msqid, sharedMemPtr);

        /* Send the file */
        send(argv[1]);

        /* Cleanup */
        cleanUp(shmid, msqid, sharedMemPtr);

        return 0;
}

Получатель. cpp:

#include <iostream>
#include <sys/shm.h>
#include <sys/msg.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "msg.h"    /* For the message struct */


/* The size of the shared memory chunk */
#define SHARED_MEMORY_CHUNK_SIZE 1000

/* The ids for the shared memory segment and the message queue */
 int shmid, msqid;

/* The pointer to the shared memory */
 void *sharedMemPtr;

/* The name of the received file */
const char recvFileName[] = "recvfile";

/**
 * Sets up the shared memory segment and message queue
 * @param shmid - the id of the allocated shared memory
 * @param msqid - the id of the shared memory
 * @param sharedMemPtr - the pointer to the shared memory
 */

 void init(int& shmid, int& msqid, void*& sharedMemPtr)
{
        std::cout<<"Creating key"<<std::endl;
        key_t key = ftok("keyfile.txt", 'a');

        shmid =shmget(key,SHARED_MEMORY_CHUNK_SIZE, 0644 | IPC_CREAT);
        std::cout<<"allocated shared memory"<<std::endl;

        sharedMemPtr = shmat(shmid,NULL,0);
        std::cout<<"Attached to shared memory"<<std::endl;

        msqid = msgget(key,0644 | IPC_CREAT);
        std::cout<<"Attahed to message queue"<<std::endl;
}

void mainLoop()
{
        /* The size of the mesage */
        int msgSize =0;

        /* Open the file for writing */
        FILE* fp = fopen(recvFileName, "w");

        /* Error checks */
        if(!fp)
        {
                perror("fopen");
                exit(-1);
        }

        std::cout<<"Waiting for message"<<std::endl;

    /* TODO: Receive the message and get the message size. The message will
     * contain regular information. The message will be of SENDER_DATA_TYPE
     * (the macro SENDER_DATA_TYPE is defined in msg.h).  If the size field
     * of the message is not 0, then we copy that many bytes from the shared
     * memory region to the file. Otherwise, if 0, then we close the file and
     * exit.
     * Keep receiving until the sender set the size to 0, indicating that
     * there is no more data to send
         */

  while(msgSize != 0){

        message recvdMsg;
        msgrcv(msqid,&recvdMsg,sizeof(recvdMsg),SENDER_DATA_TYPE,0);
        msgSize  = recvdMsg.size;
        std::cout<<"Entering main loop"<<std::endl;

        /* If the sender is not telling us that we are done, then get to work */

                if(msgSize != 0)
                {
                        /* Save the shared memory to file */
                        if(fwrite(sharedMemPtr, sizeof(char), msgSize, fp) < 0)
                        {
                                perror("fwrite");
                        }

                        /* TODO: Tell the sender that we are ready for the next file chunk.
                         * I.e. send a message of type RECV_DONE_TYPE (the value of size field
                         * does not matter in this case).
                         */
                message sentMsg;
                sentMsg.mtype = RECV_DONE_TYPE;
                std::cout<<"Ready for next file chunk"<<std::endl;
                msgsnd(msqid,&sentMsg,0,0);
                std::cout<<"Ready message sent"<<std::endl;
}

                        /* We are done */
                else
                {
                        /* Close the file */
                        fclose(fp);
                }
        }
}

void cleanUp(const int& shmid, const int& msqid, void* sharedMemPtr)
{

        printf("Detaching from shared memory\n");
        shmdt(sharedMemPtr);
        printf("Deallocating shared memory chunk\n");
        shmctl(shmid,IPC_RMID,NULL);
        printf("deallocating message queue\n");
        msgctl(msqid,IPC_RMID,NULL);
}

void ctrlCSignal(int signal)
{
        /* Free system V resources */
        cleanUp(shmid, msqid, sharedMemPtr);
}

int main(int argc, char** argv)
{

        /* TODO: Install a signal handler
         * In a case user presses Ctrl-c your program should delete message
         * queues and shared memory before exiting. You may add the cleaning functionality
         * in ctrlCSignal().
         */
        signal(SIGINT, ctrlCSignal);


        /* Initialize */
        init(shmid, msqid, sharedMemPtr);

        /* Go to the main loop */
        mainLoop();

        /** TODO: Detach from shared memory segment, and deallocate shared memory and message queue (i.e. call cleanup) **/

        std::cout<<"Cleaning up"<<std::endl;
        cleanUp(shmid, msqid, sharedMemPtr);
        std::cout<<"Finished"<<std::endl;
        return 0;
}








...