Именованные каналы как идентифицировать клиента

Предположим, у меня есть сервер, который создает изображения капчи по запросу.

Клиенты общаются с сервером через именованные каналы с 6 словами чата и идентификатором.

Сервер создает изображение и также отправляет его клиенту через именованные каналы.

У клиента есть функция create_captcha_files (const char * word), которая связывается с сервером, получает результат и сохраняет его в файле word.png.

Сервер имеет уже реализованную функцию size_t captcha (const char * word, char * buffer), которая записывает в буфер соответствующее изображение, возвращая максимальное количество записанных байтов 16384 байта.

Итак, клиент такой:

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>


int main()
{
    int fd, fdin, fdpng;
    char * myfifo = "captcha";
    char id = "001";
    char text[9];
    char buf[1024];
    char png[10];
    char palavra[6];


create_captcha_file(const char* palavra) {
    //write to fifo "captcha" the word + id
    mkfifo(myfifo, 0666);
    strcat(strcat(text,palavra),id);
    fd = open(myfifo, O_WRONLY);
    write(fd,text,9):
    close(fd);
    unlink(myfifo);

    //read anwser from server
    mkfifo(id,0666);
    fdin = open(id,O_RDONLY);
    strcat(strcat(png,palavra),".png");
    //create the .png file
    int fdpng = open(id,O_WRONLY | O_CREAT | O_APPEND,S_IRWXU);
        while((read(fdin,buf,1))) 
            {
             write(fdpng,buf,1);
             }
        close(fdpng);
        close(fdin);
     }
    unlink(id);


    return 0;
}

и сервер:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

int main()
{


    int fd;
    char texto[9];
    char palavra[6];
    char id[3];
    char * myfifo = "captcha";
    buffer[16384];

    //create and read from fifo
    mkfifo(myfifo, 0666);
    fdin = open(myfifo, O_RDONLY);
    read(fdin, texto, 9);
    close(fdin);
    //separate word from id
    for(i=0;i<=9;i++) {
        if(i<7) strcat(palavra,texto[i])
        else strcat(id,texto[i]
    }

size_t captcha(const *char palavra, char * buffer) {
    //create the captcha image and save to buffer
    buffer = create_captcha(palavra);
    return(size_of(buffer));

    }
   captcha(palavra, buffer);

    //write to pipe id the image
    mkfifo(id, 0666);
    fd = open(id, O_WRONLY);
    write(fd,buffer,size_of(buffer)):
    close(fd);
    unlink(fd);

}

person José Moreira    schedule 19.06.2016    source источник


Ответы (1)


Вы можете использовать select(), чтобы дождаться, пока что-то произойдет с несколькими файловыми дескрипторами, а затем использовать FD_ISSET(), чтобы выяснить, какой файловый дескриптор отправил сообщение.

Например:

fd_set read_set;
FD_ZERO (&read_set);
FD_SET (filedes[0], &read_set); /* filedes[0] is read end of the pipe */
FD_SET (STDIN_FILENO, &read_set); /* some other file descriptor */

Вы должны использовать FD_SET() для каждого клиента. А затем используйте select, чтобы дождаться клиентов:

if (select (nfds, &read_set, NULL, NULL, NULL) == -1)
                /* Handle error */

Хитрость здесь nfds, это максимум id файловых дескрипторов + 1.

Теперь вы не хотите проверять, какой клиент / дескриптор файла отправил сообщение? Используйте FD_ISSET()!

if (FD_ISSET (filedes[0], &read_set))
               /* Do something */
if (FD_ISSET (STDIN_FILENO, &read_set)){
               /* Do something */

Примечание. Вы должны использовать FD_ISSET() для каждого дескриптора файла / клиента.

Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать.

person Aleksandar Makragić    schedule 19.06.2016
comment
Я считаю, что мне следует избегать использования select (), потому что он не использовался в моих классах (по крайней мере, на данный момент), разве это не более простой способ? не используя идентификацию клиента, должен ли клиент какое-то время (1) находиться с открытым каналом в ожидании соединения? - person José Moreira; 20.06.2016
comment
Что ж, я думаю, вы могли бы использовать какой-нибудь большой массив, в который вы добавляете файловые дескрипторы для клиентов, а затем в одном цикле while (1) проверяйте, есть ли что-нибудь для чтения в каждом файловом дескрипторе с помощью системного вызова read (). - person Aleksandar Makragić; 21.06.2016