Я работаю над проектом с процессом отправителя и получателя, используя общую память и очередь сообщений. На всю жизнь я не могу заставить процесс получения получать файл, но я не могу понять, что на самом деле идет не так. Кажется, что он на самом деле не получает файл, или он просто застрял в бесконечном 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;
}