2016-06-19 28 views
1

Supose我有一个服务器可以根据请求创建验证码图片。命名管道如何识别客户端

客户端通过具有6个聊天字和ID的命名管道与服务器通信。

服务器创建映像并通过命名管道将其发送给客户端。

客户端具有与服务器通信并获得结果并保存在word.png文件中的函数create_captcha_files(const char * word)。

服务器有一个已经实现的函数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); 

} 

回答

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

现在,你wan't检查哪些客户机/类file_descriptor发送信息?使用FD_ISSET()

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

注:必须使用FD_ISSET()每个文件描述符/客户端。

如果您还有其他问题,请随时询问。

+0

我相信我应该避免使用select(),因为它没有在我的类中使用(至少在这一刻)不是一种更简单的方法吗? 不使用客户端标识,如果客户端需要一段时间(1),管道打开等待连接? –

+0

嗯,我想你可以使用一些大的数组,在那里你将为客户端添加文件描述符,然后在while(1)循环中检查是否有read()系统调用的每个文件描述符上要读取的内容。 –