【问题标题】:client server pipe -c客户端服务器管道-c
【发布时间】:2013-11-12 05:55:35
【问题描述】:
////   first loop it is conduct correctly but, second loop buff or path have strange value 
////   please, why can't this code conduct correctly?????
////   

#define MAXLINE 4096
#define STDOUT_FILENO 1

void client(int, int), server(int, int);

int main(int argc, char *argv[]) 
{
    char str[MAXLINE];
    int maxByte; 
    int pipe1[2], pipe2[2];
    pid_t childpid;

    while(1){

        pipe(pipe1);
        pipe(pipe2);

        if((childpid=fork())==0) /* child */    // fork() if child process return 0 
        {               // else if parent process return child_pid
        close(pipe1[0]);        // pipe[0] read end of the pipe
        close(pipe2[1]);        // pipe[1] write end of the pipe

        server(pipe2[0], pipe1[1]); 
        exit(0);
        }

        /* parent */
        close(pipe1[1]);
        close(pipe2[0]);

        client(pipe1[0], pipe2[1]);
        waitpid(childpid, NULL, 0); /* wait for child to terminate */

    }
}

void client(int readfd, int writefd)
{
    size_t len;
    size_t n;
    char buff[MAXLINE];
    char type[MAXLINE];
    char option[MAXLINE];   

    printf("<client>\n");

    /* read pathname */
    printf("path: ");
    fgets(buff, MAXLINE, stdin);

    printf("Read or Write? (r/w)");
    fgets(type, MAXLINE, stdin);

    printf("Enter correct option(r: byte / w: text)");
    fgets(option, MAXLINE, stdin);

    strcat(buff, type);
    strcat(buff, option);

    len = strlen(buff);

    if(buff[len-1] == '\n')
        len--;

    write(writefd, buff, len);

    while((n=read(readfd, buff, MAXLINE))>0) {
        write(STDOUT_FILENO, buff, n);
    }
}

void server(int readfd, int writefd) {
    int fd;
    int i = 0;
    int j = 0;
    int tk = 0;
    int ok = 0;
    int pk = 0;
    size_t n;

    char buff[MAXLINE+1];
    char path[MAXLINE];
    char type[MAXLINE];
    char option[MAXLINE];   

    if((n=read(readfd, buff, MAXLINE))==0)
    {
        printf("end-of-file");
        exit(0);
    }

    buff[n]='\0';


    while(buff[j] != '\n') {
                path[pk] = buff[j];
                j++;
                pk++;
        }

    j++;

    while(buff[j] != '\n') {
                type[tk] = buff[j];
            j++;
            tk++;
    }

    j++;

    while(buff[j] != '\0') {
        option[ok] = buff[j];
        j++;
            ok++;
    }

    printf("Path: %s\n", path);
    printf("Type: %s\n", type);
    printf("Option: %s\n", option);

    if(type[0] == 'r') {
        if((fd=open(path,O_RDONLY))<0)
        {

            snprintf(buff+n, sizeof(buff)-n, ": can't open, %s\n", strerror(errno));
            n=strlen(buff);
            write(writefd, buff, n);
        } else {

            while((n=read(fd, buff, MAXLINE))>0) {
                write(writefd, buff, atoi(option));
            }
            close(fd);
        } 
    } else if(type[0] == 'w') {
            fd=open(path, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
            write(fd, option, strlen(option));
                close(fd);
    }

}

【问题讨论】:

    标签: c linux client-server kernel


    【解决方案1】:

    一个主要问题是server() 中的代码不会终止它复制到pathtypeoption 中的字符串。

    第二个问题是服务器中的代码尝试将选项中的“r”或“w”转换为整数作为它应该写回的字节数。这转换为 0 个字节。

    #include <errno.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include "stderr.h"
    
    #define MAXLINE 4096
    #define STDOUT_FILENO 1
    
    void client(int, int);
    void server(int, int);
    
    int main(int argc, char **argv)
    {
        int pipe1[2], pipe2[2];
        pid_t childpid;
        err_setarg0(argv[argc - argc]);
        err_setlogopts(ERR_PID|ERR_STAMP);
    
        while (1)
        {
            if (pipe(pipe1) != 0) err_syserr("failed to create pipe\n");
            if (pipe(pipe2) != 0) err_syserr("failed to create pipe\n");
    
            if ((childpid = fork()) == 0) /* child */    // fork() if child process return 0
            {
                // else if parent process return child_pid
                close(pipe1[0]);    // pipe[0] read end of the pipe
                close(pipe2[1]);    // pipe[1] write end of the pipe
    
                server(pipe2[0], pipe1[1]);
                exit(0);
            }
            if (childpid < 0)
                err_syserr("failed to fork\n");
    
            /* parent */
            close(pipe1[1]);
            close(pipe2[0]);
    
            client(pipe1[0], pipe2[1]);
            int status;
            pid_t corpse = waitpid(childpid, &status, 0); /* wait for child to terminate */
            if (corpse != childpid)
                err_syserr("Wrong body: expected %d, actual %d\n", childpid, corpse);
            err_remark("Child: %d, status 0x%.4X\n", corpse, status);
            close(pipe1[0]);    // JL
            close(pipe2[1]);    // JL
        }
    }
    
    void client(int readfd, int writefd)
    {
        ssize_t len;
        ssize_t n;
        char buff[MAXLINE];
        char type[MAXLINE];
        char option[MAXLINE];
    
        printf("<client>\n");
    
        /* read pathname */
        printf("path: ");
        if (fgets(buff, MAXLINE, stdin) == 0)
            err_syserr("EOF reading path\n");
    
        printf("Read or Write? (r/w)");
        if (fgets(type, MAXLINE, stdin) == 0)
            err_syserr("EOF reading R/W\n");
    
        printf("Enter correct option(r: byte / w: text)");
        if (fgets(option, MAXLINE, stdin) == 0)
            err_syserr("EOF reading options\n");
    
        strcat(buff, type);
        strcat(buff, option);
    
        len = strlen(buff);
    
        if (buff[len-1] == '\n')
            len--;
    
        if (write(writefd, buff, len) != len)
            err_syserr("Short write on pipe\n");
        err_remark("Wrote message <<%.*s>> to server\n", (int)len, buff);
    
        while ((n = read(readfd, buff, MAXLINE)) > 0)
        {
            if (write(STDOUT_FILENO, buff, n) != n)
                err_syserr("Short write on standard output\n");
        }
    }
    
    void server(int readfd, int writefd)
    {
        int fd;
        int j = 0;
        int tk = 0;
        int ok = 0;
        int pk = 0;
        int n;
    
        char buff[MAXLINE+1];
        char path[MAXLINE];
        char type[MAXLINE];
        char option[MAXLINE];
    
        if ((n = read(readfd, buff, MAXLINE)) == 0)
        {
            printf("end-of-file\n");
            exit(0);
        }
        err_remark("Got message <<%.*s>> from client\n", (int)n, buff);
    
        buff[n] = '\0';
    
        while (buff[j] != '\n')
        {
            path[pk] = buff[j];
            j++;
            pk++;
        }
        path[pk] = '\0';
    
        j++;
    
        while (buff[j] != '\n')
        {
            type[tk] = buff[j];
            j++;
            tk++;
        }
        type[tk] = '\0';
    
        j++;
    
        while (buff[j] != '\0')
        {
            option[ok] = buff[j];
            j++;
            ok++;
        }
        option[ok] = '\0';
    
        printf("Path: %s\n", path);
        printf("Type: %s\n", type);
        printf("Option: %s\n", option);
    
        if (type[0] == 'r')
        {
            if ((fd = open(path, O_RDONLY)) < 0)
            {
                err_remark("Failed to open file %s\n", path);
                snprintf(buff+n, sizeof(buff)-n, ": can't open, %s\n", strerror(errno));
                n = strlen(buff);
                write(writefd, buff, n);
            }
            else
            {
                while ((n = read(fd, buff, MAXLINE)) > 0)
                {
                    if (write(writefd, buff, n) != n)
                        err_syserr("Short write to client\n");
                }
                close(fd);
            }
        }
        else if (type[0] == 'w')
        {
            fd = open(path, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
            write(fd, option, strlen(option));
            close(fd);
        }
    }
    

    此代码对我有用。它使用我为错误报告编写的包'stderr.[ch]'。以err_ 开头的函数都在该包中。

    示例输出:

    <client>
    path: data
    Read or Write? (r/w)r
    Enter correct option(r: byte / w: text)w
    cs: cs: 2013-10-31 21:44:16 - pid=2768: Wrote message <<data
    r
    w>> to server
    2013-10-31 21:44:16 - pid=2769: Got message <<data
    r
    w>> from client
    Path: data
    Type: r
    Option: w
    As a describer of life and manners, he must be allowed to stand perhaps
    the first of the first rank.  His humour, which, as Steele observes, is
    peculiar to himself, is so happily diffused as to give the grace of
    novelty to domestic scenes and daily occurrences.  He never "o'ersteps
    the modesty of nature," nor raises merriment or wonder by the violation
    of truth.  His figures neither divert by distortion nor amaze by
    aggravation.  He copies life with so much fidelity that he can be hardly
    said to invent; yet his exhibitions have an air so much original, that
    it is difficult to suppose them not merely the product of imagination.
    cs: 2013-10-31 21:44:16 - pid=2768: Child: 2769, status 0x0000
    <client>
    path: data
    Read or Write? (r/w)r
    Enter correct option(r: byte / w: text)w
    cs: 2013-10-31 21:44:23 - pid=2768: Wrote message <<data
    r
    w>> to server
    cs: 2013-10-31 21:44:23 - pid=2770: Got message <<data
    r
    w>> from client
    Path: data
    Type: r
    Option: w
    As a describer of life and manners, he must be allowed to stand perhaps
    the first of the first rank.  His humour, which, as Steele observes, is
    peculiar to himself, is so happily diffused as to give the grace of
    novelty to domestic scenes and daily occurrences.  He never "o'ersteps
    the modesty of nature," nor raises merriment or wonder by the violation
    of truth.  His figures neither divert by distortion nor amaze by
    aggravation.  He copies life with so much fidelity that he can be hardly
    said to invent; yet his exhibitions have an air so much original, that
    it is difficult to suppose them not merely the product of imagination.
    cs: 2013-10-31 21:44:23 - pid=2768: Child: 2770, status 0x0000
    <client>
    path: cs: 2013-10-31 21:44:25 - pid=2768: EOF reading path
    error (0) Undefined error: 0
    end-of-file
    

    如您所见,它能够毫无困难地读取同一个文件两次。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 2017-09-30
      • 2020-06-11
      相关资源
      最近更新 更多