2

my program was to be a terminal communicator between clients. So the first terminal should be a server, second and third should be clients. The servers starts with ./program --start, and the clients should log in with ./program --login [name]. Then they should write to each other with the TO [name] [message], but it doesnt work. Something is wrong with writing the message from terminal to FIFO, kind of the program dont want to respond on what i wrote in terminal. Do you know where is the problem? Im confused

//program.h
#ifndef SERVER_H
#define SERVER_H

#define MSG_SIZE 256
#define MAX_USERS 10 

typedef struct user { 
    int pid;
    char name[20];
    char fifo[50];
    int fd;
} user;

void handle_sigquit(int sig); 

#endif
//program.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include "server.h"

int num_users = 0;
user users[MAX_USERS];

void handle_sigquit(int sig)
{
    printf("Server is shuting down\n");
    exit(0);
}

void server()
{
    signal(SIGQUIT, handle_sigquit);
    mkfifo("server_fifo", 0666);
    int server_fifo = open("server_fifo", O_RDONLY | O_NONBLOCK);
    printf("Server has started.\n");

    while (1)
    {
        char buffer[1024];
        int num_read = read(server_fifo, buffer, sizeof(buffer));
        if (num_read > 0)
        {
            buffer[num_read] = '\0';
            printf("You received the message from: %s\n", buffer);

            char *name = strtok(buffer, " ");
            char *message = strtok(NULL, "\n");

            int i;
            for (i = 0; i < num_users; i++)
            {
                if (strcmp(name, users[i].name) == 0)
                {
                    write(users[i].fd, message, strlen(message));
                    printf("The message has been written to: %s.\n", name);
                    break;
                }
            }
            if (i == num_users)
            {
                printf("User doesn't exists.\n");
            }

        }
    }

}

void client(int fd, int sender_pid, char *name)
{
    if (num_users == MAX_USERS)
    {
        printf("Max users.\n");
    }

    char fifo_name[50];
    sprintf(fifo_name, "%s_fifo", name);
    mkfifo(fifo_name, 0666);
    int user_fifo = open(fifo_name, O_RDONLY | O_NONBLOCK);
    if (user_fifo == -1)
    {
        perror("open user fifo");
        exit(1);
    }

    char msg[MSG_SIZE];
    memset(msg, 0, sizeof(msg));


    while (1)
    {
        int bytes_read = read(user_fifo, msg, MSG_SIZE);
        if (bytes_read == -1)
        {
            perror("read user fifo");
            exit(1);
        }
        if (bytes_read == 0)
        {
            usleep(1000);
            continue;
        }

        char *tok = strtok(msg, " ");
        if (tok == NULL)
        {
            continue;
        }

        if (strcmp(tok, "TO") == 0)
        {

            tok = strtok(NULL, " ");
            if (tok == NULL)
            {
                continue;
            }
            int to_user = -1;
            for (int i = 0; i < num_users; i++)
            {
                if (strcmp(users[i].name, tok) == 0)
                {
                    to_user = i;
                    break;
                }
            }
            if (to_user == -1)
            {
                continue;
            }
            tok = strtok(NULL, "");
            if (tok == NULL)
            {
                continue;
            }
            int to_user_fifo = open(users[to_user].name, O_WRONLY | O_NONBLOCK);
            if (to_user_fifo == -1)
            {
                continue;
            }
            char reply[MSG_SIZE + 32];
            snprintf(reply, MSG_SIZE + 32, "FROM %s %s", fifo_name, tok);
            if (write(to_user_fifo, reply, strlen(reply) + 1) == -1)
            {
                perror("write to user fifo");
            }
            close(to_user_fifo);
        }
        else if (strcmp(tok, "REGISTER") == 0)
        {
            if (num_users >= MAX_USERS)
            {
                continue;
            }
            tok = strtok(NULL, "");
            if (tok == NULL)
            {
                continue;
            }
            /* Dodaj użytkownika */
            struct user u;
            u.pid = getpid();
            strncpy(u.name, tok, 31);
            u.name[31] = '\0';
            users[num_users++] = u;
        }
        else if (strcmp(tok, "UNREGISTER") == 0)
        {
            tok = strtok(NULL, "");
            if (tok == NULL)
            {
                continue;
            }
            int index = -1;
            for (int i = 0; i < MAX_USERS; i++)
            {
                if (users[i].pid == sender_pid)
                {
                    index = i;
                    break;
                }
            }

            if (index == -1)
            {
                char *error_msg = "ERROR: User not registered.\n";
                write(fd, error_msg, strlen(error_msg));
                exit(1);
            }

            char message[MSG_SIZE];
            volatile int msg_size = sizeof(message);
            snprintf(message, msg_size, "[%s] %s", users[index].name, msg);

            for (int i = 0; i < MAX_USERS; i++)
            {
                if (users[i].pid != 0 && users[i].pid != sender_pid)
                {
                    int user_fifo = open(users[i].fifo, O_WRONLY | O_NONBLOCK);
                    if (user_fifo != -1)
                    {
                        write(user_fifo, message, strlen(message));
                        close(user_fifo);
                    }

                }
            }
        }
    }
}

int main(int argc, char *argv[])
{
    int fd;
    int sender_pid = -1;
    char *name = argv[2];
    if (argc == 2 && strcmp(argv[1], "--start") == 0)
    {
        server();
    }
    else if (argc == 3 && strcmp(argv[1], "--login") == 0)
    {
        client(fd, sender_pid, name);
    }
}


I tried a lot, most of changing something with fifo's code.

Matthew
  • 21
  • 3
  • To make the program more understandable, split the server and client into separate functions that you call from `main()` after checking the argument. – Barmar May 07 '23 at 22:41
  • There's no need for the `total_read` variable. You're zeroing it each time through the loop, so just use `num_read`. – Barmar May 07 '23 at 22:45
  • You never fill in `users[i]` in the server, only the client. How is the server supposed to write to the client? – Barmar May 07 '23 at 22:49
  • And the clients never write to the server fifo. – Barmar May 07 '23 at 22:50
  • I made some changes in code to make it more understandable as you said. I think i need to save client messages to server fifo and then read from this. Is it a good way to solve the problem? – Matthew May 07 '23 at 23:34
  • You haven't solved the design problem that the client and server are using different fifos. – Barmar May 08 '23 at 02:32
  • You seem to be assuming that the `users` and `num_users` variables are shared between the clients and server. – Barmar May 08 '23 at 02:33

0 Answers0