-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsender.cpp
251 lines (207 loc) · 6.81 KB
/
sender.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#include <sys/shm.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "msg.h" /* For the message struct */
/* The size of the shared memory segment */
#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 allocated message queue
*/
void init(int& shmid, int& msqid, void*& sharedMemPtr)
{
/* TODO:
1. Create a file called keyfile.txt containing string "Hello world" (you may do
so manually or from the code).
2. Use ftok("keyfile.txt", 'a') in order to generate the key.
3. Use will use this key in the TODO's below. Use the same key for the queue
and the shared memory segment. This also serves to illustrate the difference
between the key and the id used in message queues and shared memory. The key is
like the file name and the id is like the file object. Every System V object
on the system has a unique id, but different objects may have the same key.
*/
key_t key = ftok("keyfile.txt", 'a');
/* the ftok function creates a sort of identifier to be used with the System V IPC functions*/
if(key == -1)
{
perror("ftok");
exit(-1);
}
/* error check*/
/* TODO: Get the id of the shared memory segment. The size of the segment must be SHARED_MEMORY_CHUNK_SIZE */
shmid = shmget(key,SHARED_MEMORY_CHUNK_SIZE, 0644|IPC_CREAT);
/* creates the segment with 644 permissions, all users can read & the file's owner can read and write*/
if(shmid == -1)
{
perror("shmget");
exit(-1);
}
/* error ckeck */
/* TODO: Attach to the shared memory */
sharedMemPtr = (char*) shmat(shmid, NULL, 0);
if(sharedMemPtr == (char*)(-1) )
{
perror("shmat");
exit(-1);
}
/* error check, cast used during the comparison*/
/* TODO: Attach to the message queue */
msqid = msgget(key, 0666|IPC_CREAT);
/* 0666 <- read & write file permissions */
if(msqid == -1)
{
perror("shmget");
exit(-1);
}
/* error ckeck */
/* Store the IDs and the pointer to the shared memory region in the corresponding function parameters */
}
/**
* Performs the cleanup functions
* @param sharedMemPtr - the pointer to the shared memory
* @param shmid - the id of the shared memory segment
* @param msqid - the id of the message queue
*/
void cleanUp(const int& shmid, const int& msqid, void* sharedMemPtr)
{
/* TODO: Detach from shared memory */
if(shmdt(sharedMemPtr) == -1)
{
perror("shmdt");
exit(-1);
}
/* error check while detach*/
}
/**
* The main send function
* @param fileName - the name of the file
* @return - the number of bytes sent
*/
unsigned long sendFile(const char* fileName)
{
/* A buffer to store message we will send to the receiver. */
message sndMsg;
/* A buffer to store message received from the receiver. */
ackMessage rcvMsg;
/* The number of bytes sent */
unsigned long numBytesSent = 0;
/* Open the file */
FILE* fp = fopen(fileName, "r");
/* Was the file open? */
if(!fp)
{
perror("fopen");
exit(-1);
}
/* Read the whole file */
while(!feof(fp))
{
/* Read at most SHARED_MEMORY_CHUNK_SIZE from the file and
* store them in shared memory. fread() will return how many bytes it has
* actually read. This is important; the last chunk read may be less than
* SHARED_MEMORY_CHUNK_SIZE.
*/
if((sndMsg.size = fread(sharedMemPtr, sizeof(char), SHARED_MEMORY_CHUNK_SIZE, fp)) < 0)
{
perror("fread");
exit(-1);
}
/* includes error check*/
/* TODO: count the number of bytes sent. */
numBytesSent = sndMsg.size + numBytesSent;
/* TODO: Send a message to the receiver telling him that the data is ready
* to be read (message of type SENDER_DATA_TYPE).
*/
sndMsg.mtype = SENDER_DATA_TYPE;
if(msgsnd(msqid, &sndMsg, sizeof(message)-sizeof(long), 0) == -1)
{
perror("msgsnd");
exit(-1);
}
/* set message type & error check & send message */
/* TODO: Wait until the receiver sends us a message of type RECV_DONE_TYPE telling us
* that he finished saving a chunk of memory.
*/
do
{
msgrcv(msqid, &rcvMsg, sizeof(ackMessage)-sizeof(long), RECV_DONE_TYPE, 0);
}while(rcvMsg.mtype != RECV_DONE_TYPE);
/* receiver keep receiving until the finished saving e.g the RECV_DONE_TYPE done*/
}
/** 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;
if(msgsnd(msqid, &sndMsg, sizeof(message) - sizeof(long), 0) == -1)
{
perror("msgsn");
exit(-1);
}
/* error check */
/* Close the file */
fclose(fp);
return numBytesSent;
}
/**
* Used to send the name of the file to the receiver
* @param fileName - the name of the file to send
*/
void sendFileName(const char* fileName)
{
/* Get the length of the file name */
int fileNameSize = strlen(fileName);
/* TODO: Make sure the file name does not exceed
* the maximum buffer size in the fileNameMsg
* struct. If exceeds, then terminate with an error.
*/
if(fileNameSize > MAX_FILE_NAME_SIZE)
{
perror("fileNameSize EXCEEDS");
exit(-1);
}
/* TODO: Create an instance of the struct representing the message
* containing the name of the file.
*/
fileNameMsg msgName;
/* TODO: Set the message type FILE_NAME_TRANSFER_TYPE */
msgName.mtype = FILE_NAME_TRANSFER_TYPE;
/* TODO: Set the file name in the message */
strncpy(msgName.fileName, fileName, fileNameSize++);
/* copy the charcters from string fileName into the destination
* (e.g. instance msgName)
*/
/* TODO: Send the message using msgsnd */
if(msgsnd(msqid, &msgName, sizeof(fileNameMsg)-sizeof(long),0) == -1)
{
perror("sgnsnd");
exit(-1);
}
/* error check & sending message*/
}
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 name of the file */
sendFileName(argv[1]);
/* Send the file */
fprintf(stderr, "The number of bytes sent is %lu\n", sendFile(argv[1]));
/* Cleanup */
cleanUp(shmid, msqid, sharedMemPtr);
return 0;
}