客户端服务器管道-c

标签 c linux client-server kernel

////   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);
    }

}

最佳答案

一个主要问题是 server() 中的代码不会以 null 终止它复制到 pathtype选项

第二个问题是服务器中的代码尝试将选项中的“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

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

关于客户端服务器管道-c,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19719868/

相关文章:

c - GCC 和在其他文件中声明的内联 C 函数( "function body not available"问题)

linux -/proc/$pid/maps 显示在 x86_64 linux 上没有 rwx 权限的页面

delphi - 当客户端连接崩溃时如何释放服务器 DCOM 中的引用

具有服务器和客户端的项目的 Git 存储库设置

C语言基础1

c - 遇到错误: invalid operands to binary & and error: invalid operands to binary |?怎么办

c - 如何避免在 MPI 中将可执行文件从主节点复制到从节点?

linux - 如何使用单个 ack 命令更改嵌套在子目录中的文件的权限?

linux - 如何在 Linux 中解码/proc/pid/pagemap 条目?

java - 通过套接字监听客户端时程序卡住