Client Server using named pipes with threads and fork in CC
Solution
Pipe is one of the message passing IPC resource widely used on unix operating system platforms. Pipes provide
unidirectional interprocess communication channel. A pipe has a read end and a write end. Data written to the
write end of a pipe can be read from the read end of the pipe.pipes can be created using pipe api, which creates a new pipe and returns two file descriptors, one referring to the read end of the pipe, the other referring to the write end. Pipes can be used to create a communication channel between related processes.
Client-Server program.
#include <stdio. h>
#include <stdlib. h>
#include <unistd. h>
#include <string. h>
void client(int readfd, int writefd)
{
char msg[ 100] ;
int n;
char eof = EOF;
printf(\"%d enter msg to be sent to server: \", getpid() ) ;
fgets(msg, 100, stdin) ;
if (write(writefd, msg, strlen(msg) 1) == 1) {
perror(\"error writing. . . \") ;
exit(0) ;
perror(\"error reading. . . \") ;
exit(0) ;
}m
sg[ n] = \' \' ;
printf(\"received from server: %sn\", msg) ;
}
void server(int readfd, int writefd)
{
char msg[ 100] ;
int n;
if ((n = read(readfd, msg, 100) ) < 0) {
perror(\"error reading. . . \") ;
}m
sg[ n] = \' \' ;
printf(\"%d server received from client: %sn\", getpid() , msg) ;
printf(\"enter msg to be sent to client: \") ;
fgets(msg, 100, stdin) ;
write(writefd, msg, strlen(msg) 1) ;
}i
nt main()
{
int pipe1fd[ 2] , pipe2fd[ 2] ;
int pid;
/* create two pipes */
if (pipe(pipe1fd) == 1) {
perror(\"pipe: \") ;
return 0;
}i
f (pipe(pipe2fd) == 1) {
perror(\"pipe: \") ;
return 0;
}
/* start child process and run client code in it */
pid = fork() ;
if (pid == 0) {
close(pipe1fd[ 1] ) ; //close the write end of the first pipe
close(pipe2fd[ 0] ) ; //close the read end of the second pipe
client(pipe1fd[ 0] , pipe2fd[ 1] ) ;
exit(0) ;
}e
lse {
/* code that runs in parent ; runs as server */
close(pipe1fd[ 0] ) ; // close read end of the first pipe
close(pipe2fd[ 1] ) ; // close write end of the second pipe
server(pipe2fd[ 0] , pipe1fd[ 1] ) ;
wait(NULL) ; //wait for child process to finish
return 0;
}
}
The following program creates a pipe, and then forks to create a child process the child inherits pipe file
descriptors that refer to the same pipe. After fork() each process closes the descriptors that it doesn’t need for
the pipe . The parent then waits on pipe1 for data and child process sends a string message , for which parent
sends response message through pipe2, and the child reads this string a byte at a time from the pipe and echoes it on standard output.
Shared memory:Shared memory is what the name says about it: a segment of memory shared between several processes.Shared memory in UNIX is based on the concept of memory mapping. The segment of memory shared is coupled with an actual file in the filesystem. The file content is a mirror of the memory segment at any time. The mapping between the shared segment content and the mapped file is persistent.
/*
* shm_msgclient.c
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
#define MAX_MSG_LENGTH
#define SHMOBJ_PATH /*shared memory object path*/
#define TYPES 8
struct msg_s {
int type;
char content[MAX_MSG_LENGTH];
};
int main(int argc, char *argv[]) {
int shmfd;
int shared_seg_size = (1 * sizeof(struct msg_s));
struct msg_s *shared_msg;
shmfd = shm_open(SHMOBJ_PATH, O_RDWR, S_IRWXU | S_IRWXG);
if (shmfd < 0) {
perror(\"In shm_open()\");
exit(1);
}
printf(\"Created shared memory object %s\ \", SHMOBJ_PATH);
shared_msg = (struct msg_s *)mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
if (shared_msg == NULL) {
perror(\"In mmap()\");
exit(1);
}
printf(\"Shared memory segment allocated correctly (%d bytes).\ \", shared_seg_size);
printf(\"Message type is %d, content is: %s\ \", shared_msg->type, shared_msg->content);
return 0;
}
/*
* shm_msgserver.c */
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
#define MAX_MSG_LENGTH
#define TYPES
struct msg_s {
int type;
char content[MAX_MSG_LENGTH];
};
int main(int argc, char *argv[]) {
int shmfd;
int shared_seg_size = (1 * sizeof(struct msg_s));
struct msg_s *shared_msg;
shmfd = shm_open(SHMOBJ_PATH, O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG);
if (shmfd < 0) {
perror(\"In shm_open()\");
exit(1);
}
fprintf(stderr, \"Created shared memory object %s\ \", SHMOBJ_PATH);
ftruncate(shmfd, shared_seg_size);
shared_msg = (struct msg_s *)mmap(NULL, shared_seg_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
if (shared_msg == NULL) {
perror(\"In mmap()\");
exit(1);
}
fprintf(stderr, \"Shared memory segment allocated correctly (%d bytes).\ \", shared_seg_size);
srandom(time(NULL));
shared_msg->type = random() % TYPES;
snprintf(shared_msg->content, MAX_MSG_LENGTH, \"My message, type %d, num %ld\", shared_msg->type, random());
if (shm_unlink(SHMOBJ_PATH) != 0) {
perror(\"In shm_unlink()\");
exit(1);
}
return 0;
}
compile using : gcc -o shm_msgserver shm_msgserver.c and
gcc -o shm_msgclient shm_msgclient.c
Run:
./shm_msgserver
./shm_msgclient







