UNIX网络编程卷2进程间通信读书笔记(三)—有名管道 (2)

4.单个服务器,多个客户

       FIFO的真正优势表现在服务器可以是一个长期运行的进程(例如守护进程),而且与其客户可以无亲缘关系。作为服务器的守护进程以某个众所周知的路径创建一个FIFO,并打开该FIFO来读。此后某个时刻启动的客户打开该发FIFO来写,并将其命令或给守护进程的其他任何东西通过该FIFO发送出去。这种形式的单向通信(从客户到服务器)使用FIFO很容易实现,但是如果守护进程需要向客户发送回一些东西,事情就困难了。下面是一个解决办法。

       服务器以一个众所周知的路径名创建一个FIFO,它将从这个FIFO读入客户的请求。每个客户在启动时创建自己的FIFO,所用的路径名包含有自己的进程ID。每个客户把自己的请求写入服务器的众所周知FIFO中,该请求含有客户的进程ID以及一个路径名,具有该路径名的文件就是客户希望服务器打开并发回的文件。

       下面是这个程序

/*1_7.c server*/

 

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#define MALINE 1000

#define SERV_FIFO “/root/jincheng/server”

 

void server(int,int);

ssize_t readline(int fd,void *vptr,size_t maxlen);

int main(int argc,char **argv)

{

    int readfifo,writefifo,dummyfd,fd;

char *ptr,buff[MAXLINE],fifoname[MAXLINE];

pid_t pid

ssize_t n;

 

if((mkfifo(SERV_FIFO,O_CREAT)<0)&&(errno!=EEXIST))

    printf(“can’t create %s”,SERV_FIFO);

readfifo=open(SERV_FIFO,O_RDONLY,0);

dummyfd=open(SERV_FIFO,O_WRONLY,0);

while((n=readline(readfifo,buff,MAXLINE))>0)

{

    if(buff[n-1]==’/n’;

        n--;

    buff[n]=’/0’;

    if((ptr=strchr(buff,’ ‘))==NULL)

    {

        printf(“bogus request:%s/n”,buff);

        continue;

    }

    *ptr++=0;

    pid=atoll(buff);

    snprintf(fifoname,sizeof(fifoname),”/tmp/fifo.%ld”,(long)pid);

    if((writefifo=open(fifoname,O_WRONLY,0))<0)

    {

        printf(“cannot open:%s”,fifoname);

        continue;

    }

    if((fd=open(ptr,O_RDONLY))<0)

    {

        snprintf(buff+n,sizeof(buff)-n,”:can’t open %s/n”,srterror(errno));

        n=strlen(ptr);

        write(writefifo,ptr,n);

        close(writefifo);

    }

    else

    {

        while((n=read(fd,buff,MAXLINE))>0)

            write(writefifo,buff,n);

        close(fd);

        close(writefifo);

     }

}

exit(0);

}

 

ssize_t readline(int fd,void *vptr,size_t maxlen)

{

ssize_t n,rc;

char c,*ptr;

ptr=vptr;

for(n=1;n<maxlen;n++)

{

    again:

    if((rc=read(fd,&c,1))==1)

    {

        *ptr++=c;

        if(c==’/n’;)

            break;

    }

    else if(rc==0)

    {

        *ptr=0;

        return (n-1);

    }

    else

    {

        if(errno==EINTR)

            goto again;

        return (-1);

     }

}

*ptr=0;

return(n);

}

 

 

 

/*1_8.c  client*/

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#define MALINE 1000

#define SERV_FIFO “/root/jincheng/server”

 

int main(int argc,char **argv)

{

    int readfifo,writefifo;

char *ptr,buff[MAXLINE],fifoname[MAXLINE];

pid_t pid

ssize_t n;

 

pid=getpid();

snprintf(fifoname,sizeof(fifoname),”/tem/fifo.%ld”,(long)pid);

printf(“%s/n”,fifoname);

if((mkfifo(fifoname,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))

    printf(“can’t create %s”,fifoname);

snprintf(buff,sizeof(buff),”%d”,(long)pid);

len=strlen(buff);

ptr=buff+len;

writefifo=open(SERV_FIFO,O_WRONLY,0);

while(1)

{

    printf(“client:”);

    fgets(ptr,MAXLINE-len,stdin);

    len=strlen(buff);

    write(writefifo,buff,len);

}

readfifo=open(fifoname,O_RDONLY,0);

while((n=read(readfifo,buff,MAXLINE))>0)

    write(STDOUT_FILENO,buff,n);

close(readfifo);

unlink(fifoname);

exit(0);

}

你可能感兴趣的:(编程,unix,网络,server,服务器,读书)