Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The idea of my program is to use pthreads, semaphores, posix shared memory, and sockets to create an environment where N processes (that we will refer to as the children) can connect to a single process (that we will refer to as the parent) in order to send it data.

Requirements

Common Code

The parent and child processes are only allowed, and must have, 2 globally defined (#define) variables. It is these values that provide for a common means for these processes to establish a connection. These values will define the main semaphore and the shared memory segment.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <stdbool.h>
#include <sys/ipc.h> 
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include <fcntl.h>

#define SEM_KEY     ftok("commoncode.c", 'a')
#define SHARED_MEM  "/vector_table"

struct v_table
{
    pid_t PID;
    int Sem;
    int Port;
};

Parent Code

#include "commoncode.c"

#define MAX_LENGTH  512
#define MAX_CHILD   5

pthread_barrier_t   barrier;
struct v_table Vector[MAX_CHILD];

char *ok = "<ok>\n";
key_t key;
static int semcnt = 0;

union semun {
    int val;               /* used for SETVAL only */
};

void *client_serv(void * argum) {
    int msg_len, client_socket = *(int *)argum, semid0, semid1;
    char text[20];
    union semun arg;

    while (1) {
        semid0 = semget(key + semcnt, 0, IPC_CREAT | 0666);
        if ((volatile int)semctl(semid0, 0, GETVAL, 0) != 1) {
            arg.val = 1;
            semctl(semid0, 0, SETVAL, arg);
            msg_len = recv(client_socket, text, 20, 0);
            printf("%s\n", text);
            if(msg_len <= 0) {
                printf("Incorrect name from client");
                return (void *)1;
            }
            semcnt++;
            if (semcnt == MAX_CHILD)
                semcnt = 0;
            semid1 = semget(key + semcnt, 0, IPC_CREAT | 0666);
            arg.val = 0;
            semctl(semid1, 0, SETVAL, arg);
            if (!strcmp(text, "terminate"))
                break;
            memset(text, 0, 20);
            if (send(client_socket, ok, strlen(ok), 0) != strlen(ok)) {
                printf("Error : send() sent a different number of bytes\n");
                return (void *)1;
            }
        } 
    }

    pthread_barrier_wait (&barrier);
    if (send(client_socket, ok, strlen(ok), 0) != strlen(ok)) {
        printf("Error : send() sent a different number of bytes\n");
        return (void *)1;
    }

    return (void *)0;
}

int main(int argc, char *argv[])
{
    int i, fd;
    int servSock, clntSock[MAX_CHILD], i1=1;
    struct sockaddr_in echoServAddr;
    pthread_t threads[MAX_CHILD];
    uint8_t * mapped_ptr;
    union semun arg;

    for (i = 0; i < MAX_CHILD; i++) {
        Vector[i].PID  = 0;
        Vector[i].Sem  = 0;
        Vector[i].Port = i + 49153;
    }

    fd = shm_open(SHARED_MEM, O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR);
    if(fd == -1) {
        perror("shm_open");
        shm_unlink (SHARED_MEM);
        return 1;
    }
    ftruncate(fd, MAX_CHILD * sizeof(struct v_table));
    mapped_ptr = mmap(NULL, MAX_CHILD * sizeof(struct v_table), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(mapped_ptr < 0) {
        perror("mmap");
        shm_unlink (SHARED_MEM);
        return 1;
    }

    key = SEM_KEY;

    for (i = 0; i < MAX_CHILD; i++) {
        Vector[i].Sem = semget(key + i, 1, IPC_CREAT | 0666);
        arg.val = 0;
        semctl(Vector[i].Sem, 0, SETVAL, arg);
    }

    memcpy(mapped_ptr, Vector, MAX_CHILD * sizeof(struct v_table));
    msync(mapped_ptr, MAX_CHILD * sizeof(struct v_table), MS_SYNC);

    printf("Vector table (from Parent)\n");
    printf("-----------------------------\n");
    printf("PID  Semaphore      Port\n");
    for (i = 0; i < MAX_CHILD; i++)
        printf("%04d %06d       %05d\n", (int)(Vector[i].PID), Vector[i].Sem, Vector[i].Port);
    if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        printf("Error : Socket failed\n");
        return 1;
    }
    setsockopt(servSock, SOL_SOCKET, SO_REUSEADDR, &i1, sizeof(i1));
    memset(&echoServAddr, 0, sizeof(echoServAddr));
    echoServAddr.sin_family = AF_INET;
    echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    echoServAddr.sin_port = htons(Vector[0].Port);
    if (bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0) {
        printf("bind() failed\n");
        return 1;
    }

    /* Mark the socket so it will listen for incoming connections */
    if (listen(servSock, MAX_CHILD) < 0) {
        printf("Listen() failed\n");
        return 1;
    }

    for (i = 0; i < MAX_CHILD; i++) {
        if ((clntSock[i]=accept(servSock,(struct sockaddr*)NULL,(socklen_t *)NULL)) < 0) {
            printf("accept() failed\n");
            return 1;
        }
    }

    pthread_barrier_init (&barrier, NULL, MAX_CHILD);
    for (i = 0; i < MAX_CHILD; i++) {
        pthread_create(&threads[i], NULL, client_serv,(void *)(&clntSock[i]));
    }

    while (i)
        pthread_join(threads[--i], NULL);

    for (i = 0; i < MAX_CHILD; i++) {
        close(clntSock[i]);
        semctl(Vector[i].Sem, 0, IPC_RMID);
    }
    getchar();
    shm_unlink (SHARED_MEM);
    return 0;
}

Child Code

#include "commoncode.c"

#define MAX_LENGTH 512
#define MAX_CHILD   5

struct v_table Vector[MAX_CHILD];

uint8_t * mapped_ptr;
char *ok = "<ok>\n";

int main(int argc, char *argv[])
{
    int server_socket, echoServPort, i, n, attmpt = 0, fd;
    char *ipaddrstr, *text[3];
    struct sockaddr_in echoServAddr;

    if (1 == argc) {
        printf("Error - You must include a data size: ./child N.\n");
        return 1;
    } else if (2 != argc) {
        printf("Error : Too many arguments\n");
        return 1;
    }
    for(i=0 ; i<3 ; i++) {
        text[i] = malloc(MAX_LENGTH);
                memset(text[i], 0, MAX_LENGTH);
    }

    fd = shm_open(SHARED_MEM, O_RDWR | O_APPEND, S_IRUSR | S_IWUSR);
    if(fd == -1) {
        perror("shm_open");
        shm_unlink (SHARED_MEM);
        return 1;
    }
    ftruncate(fd, MAX_CHILD * sizeof(struct v_table));
    mapped_ptr = mmap(NULL, MAX_CHILD * sizeof(struct v_table), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(mapped_ptr < 0) {
        perror("mmap");
        shm_unlink (SHARED_MEM);
    }

    memcpy((void *)Vector, (void *)mapped_ptr, MAX_CHILD * sizeof(struct v_table));
    ipaddrstr = malloc(16);
    memcpy(ipaddrstr, "127.0.0.1", strlen("127.0.0.1"));

    if ((server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        printf("socket() failed\n");
        return 1;
    }
    echoServAddr.sin_family = AF_INET;  /* Internet address family */
    echoServAddr.sin_addr.s_addr = inet_addr(ipaddrstr); /* Server IP address */

    for (i = 0; i < MAX_CHILD; i++) {
        if (Vector[i].PID == 0) {
            Vector[i].PID = getpid();
            break;
        }
        attmpt++;
    }
    printf("Vector table (from %04d)\n", getpid());
    printf("-----------------------------\n");
    printf("PID  Semaphore  Port\n");

    for (i = 0; i < MAX_CHILD; i++)
        printf("%04d %04d       %05d\n", (int)(Vector[i].PID), Vector[i].Sem, Vector[i].Port);

    if (attmpt == MAX_CHILD) {
        printf("Error - No space left in vector table\n");
        getchar();
        return 1;
    }


    for (i = 0; i < MAX_CHILD; i++) {
        echoServPort = 49153 + i;
        echoServAddr.sin_port = htons(echoServPort); /* Server port */

        if (connect(server_socket, (struct sockaddr*) &echoServAddr,sizeof(echoServAddr)) < 0) {
            printf("Error Connecting\n");
            getchar();
            return 1;
        } else {
            break;
        }
    }

    mapped_ptr = memcpy((void *)mapped_ptr, (void *)Vector, MAX_CHILD * sizeof(struct v_table));
    msync(mapped_ptr, MAX_CHILD * sizeof(struct v_table), MS_SYNC);

    sscanf(argv[1], "%d", &n);
    for (i = 0; i < n; i++) {
        sprintf(text[1], "Child %04d %d", getpid(), i);
        if (send(server_socket, text[1], strlen(text[1]), 0) != strlen(text[1])) {
            printf("Error : send() sent a different number of bytes\n");
            return 1;
        }
        recv(server_socket, text[2], MAX_LENGTH, 0);
        if(strcmp (text[2], ok)) {
            printf("Error : Wrong Secret\n");
            shutdown(server_socket, 2);
            return 1;
        }
        memset(text[1], 0, MAX_LENGTH);
        memset(text[2], 0, MAX_LENGTH);
    }

    sprintf(text[1], "terminate");
    if (send(server_socket, text[1], strlen(text[1]), 0) != strlen(text[1])) {
        printf("Error : send() sent a different number of bytes\n");
        return 1;
    }
    recv(server_socket, text[2], MAX_LENGTH, 0);
    if(strcmp (text[2], ok)) {
        printf("Error : Wrong Secret\n");
        shutdown(server_socket, 2);
        return 1;
    }
    free(ipaddrstr);

    getchar();
    shm_unlink (SHARED_MEM);
    return 0;
}
share|improve this question
    
@JS1 Can you assist? – user3337714 Dec 8 '15 at 7:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.