2
\$\begingroup\$

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;
}
\$\endgroup\$
  • \$\begingroup\$ @JS1 Can you assist? \$\endgroup\$ – user3337714 Dec 8 '15 at 7:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.