For an assignment I had to create a client and a server that communicate over a well known FIFO. The server is required to use three threads to serve the client, managed by a semaphore.
The code was pretty hastily written due to my busy schedule, but works as intended from what testing I've done. Feel free to rip it apart.
info.h:
#ifndef INFO_H
#define INFO_H
#define SERVER_FILENAME "fifo.dat"
#define CLIENT_FILENAME "back.dat"
#define MAX_MSG_SIZE 15
#endif // INFO_H
server.c:
#include <fcntl.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <semaphore.h>
#include <unistd.h>
#include "info.h"
void cleanup(void)
{
unlink(SERVER_FILENAME);
unlink(CLIENT_FILENAME);
}
void listener(void *sem)
{
char buf[BUFSIZ] = "";
int err = 0;
while (true)
{
sem_wait(sem);
/* open, read, and display the message from the FIFO */
int client_to_server = open(SERVER_FILENAME, O_RDONLY);
int server_to_client = open(CLIENT_FILENAME, O_WRONLY);
if (client_to_server < 0 || server_to_client < 0)
{
fputs("Unable to open FIFOs for reading\n", stderr);
cleanup();
return;
}
err = read(client_to_server, buf, BUFSIZ);
if (err < 0)
{
fputs("Unable to read from FIFO\n", stderr);
cleanup();
return;
}
// close for reopening with new client
close(client_to_server);
if (strcmp("exit",buf) == 0)
{
printf("Server OFF.\n");
write(server_to_client, "killed", strlen("killed"));
close(server_to_client);
cleanup();
exit(0);
}
else
{
printf("Received: %s\n", buf);
printf("Sending back...\n");
char *new = strcat(buf, "-check");
write(server_to_client, new, strlen(new));
}
close(server_to_client);
/* clean buf from any data */
memset(buf, 0, sizeof(buf));
sem_post(sem);
}
cleanup();
}
int main(void)
{
int err = 0;
char *myfifo = SERVER_FILENAME;
char *myfifo2 = CLIENT_FILENAME;
/* create the FIFO (named pipe) */
err = mkfifo(myfifo, 0666);
if (err < 0)
{
fputs("Error creating FIFO\n", stderr);
cleanup();
return 1;
}
err = mkfifo(myfifo2, 0666);
if (err < 0)
{
fputs("Error creating FIFO\n", stderr);
cleanup();
return 2;
}
printf("Server ON.\n");
// unlink then initialize semaphore to 1 so locking works
sem_unlink("mysem");
sem_t *sem = sem_open("mysem", O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1);
if (sem == SEM_FAILED)
{
fputs("Unable to initialize semaphore\n", stderr);
cleanup();
return 3;
}
// initialize threads
int num_threads = 3;
pthread_t *tid = malloc(num_threads * sizeof(pthread_t));
for(int i = 0; i < num_threads; ++i)
{
err = pthread_create(tid + i, NULL, (void*)listener, sem);
if (err)
{
fputs("Unable to create threads\n", stderr);
cleanup();
return 4;
}
}
for(int i = 0; i < num_threads; ++i)
{
err = pthread_join(tid[i], NULL);
if (err)
{
fputs("Unable to join threads\n", stderr);
cleanup();
return 5;
}
}
cleanup();
}
client.c:
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "info.h"
int main(void)
{
char *myfifo = SERVER_FILENAME;
char *myfifo2 = CLIENT_FILENAME;
char str[BUFSIZ] = "";
char rec[BUFSIZ] = "";
printf("Input message to server: ");
scanf("%s", str);
/* write str to the FIFO */
int client_to_server = open(myfifo, O_WRONLY);
int server_to_client = open(myfifo2, O_RDONLY);
write(client_to_server, str, sizeof(str));
read(server_to_client, rec, sizeof(rec));
printf("...received from the server: %s\n", rec);
close(client_to_server);
close(server_to_client);
}
cleanup
once for each thread, and once for main? I don't know if this is OK from the point of whatunlink
does if it is already unlinked, but seems to be overly redundant sincecleanup
doesn't look like it is thread specific. It also looks like a possible bug sincecleanup
mayunlink
while other threads are still active... \$\endgroup\$ – Ron Beyer Nov 16 '16 at 18:31read
and its error handling, but I was having problems when I blocked only that bit of code. \$\endgroup\$ – syb0rg Nov 16 '16 at 18:48