命名管道如何识别客户端

Posted

技术标签:

【中文标题】命名管道如何识别客户端【英文标题】:Named pipes how to identify client 【发布时间】:2016-06-19 18:59:32 【问题描述】:

假设我有一个根据请求创建验证码图像的服务器。

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

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

客户端具有函数 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);


【问题讨论】:

【参考方案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,它是文件描述符ids + 1的最大值。

现在,您不想检查哪个客户端/文件描述符发送了消息?使用FD_ISSET()

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

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

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

【讨论】:

我相信我应该避免使用 select() 因为它还没有在我的课程中使用(至少目前)不是更简单的方法吗?不使用客户端标识,客户端是否应该在一段时间(1)打开管道等待连接? 好吧,我想您可以使用一些大数组,在其中为客户端添加文件描述符,然后在一个 while(1) 循环中使用 read() 系统检查每个文件描述符上是否有要读取的内容打电话。

以上是关于命名管道如何识别客户端的主要内容,如果未能解决你的问题,请参考以下文章

如何将命名管道c#服务器连接到命名管道php客户端

C#命名管道,如何检测客户端断开连接

命名管道:服务器端如何知道客户端已断开连接?

命名管道 232 管道正在关闭

如何使用重叠 I/O 检测到命名管道服务器的客户端连接?

命名管道服务器,如何中断或超时等待客户端连接和传入数据