2

ここでは、パイプを使用して単純なクライアントとサーバーを作成しようとしています。子をクライアントとして機能させ、親をサーバーとして機能させるプロセスをフォークします。以下はコードです:

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>

void errorMsg(char* msg)
{
    printf("\n%s\n", msg);
//  exit(0);
}

int main()
{
    int servfd[2];
    int clntfd[2];
    int chldpid;    

    if(pipe(servfd) < 0)
        errorMsg("Unable to create server pipe.!!");
    if(pipe(clntfd) < 0)
        errorMsg("Unable to create client pipe.!!!");
        
    if((chldpid = fork()) == 0)
    {
        char* txt = (char*) calloc(256, sizeof(char));
        close(servfd[1]);
        close(clntfd[0]);
        printf("@Client: Enter a string: ");
        //scanf("%s", txt);  //or fgets
        printf("Entered.!!");
        int n;
        txt = "Anything that you want will not be considered no matter what you do!!";
        char txt1[256];
        write(clntfd[1], txt, 256);
        
        //if(txt1[strlen(txt1) - 1] = '\n')
        //{ printf("asdasdas");
        //txt[strlen(txt) - 1] = '\0';}

        //int i = 0;
        //for(i = 0; i < 256; i++)
            //printf("%c", txt1[i]);

    while((n = read(servfd[0], txt1, 256)) > 0)
                    printf("\nAt client: %d bytes read\n\tString: %s\n", n, txt1);
}
    else    
    {
        //printf("Parent:   \n\n");
        close(servfd[0]);
        close(clntfd[1]);
        char* txt = NULL;
        int n, n1;  
        n = read(clntfd[0], &txt, 256);
        printf("Server read: %d", n);
        n1 = write(servfd[1], &txt, 256);
        printf("Server write: %d", n1);
        wait(chldpid);
    }
    exit(0);            
}

質問1:

これが起こっていることです。プログラムを実行すると、Anything that yo(正確に16文字)しか出力されず、他には何も出力されません。コメントに示されているループのtxt1使用の完全な内容を確認しようとすると、の後にnull値(神はどこから知っているか)があることがわかりました。その後は本来の内容になります。なぜこれが起こっているのか考えていますか?foryotxt1

編集:

適切な場所に印刷しようとすると、読み書きされたバイト数はす​​べて正しいです。印刷し256 bytes readます。ただし、txt1bystrlenのサイズは「16」になります。また、文字列の一部を印刷した後、プログラムがハングします。

質問2:

scanfを使用して、またはコメントに表示されているユーザーから文字列を取得しようとすると、fgetsEnterキーを押すとすぐにプログラムが終了します。なぜそれが起こっているのかについても、それについての手がかりはありません。

行動に関する洞察は役に立ちます。複数の質問でごめんなさい。御時間ありがとうございます。!私はubuntu12.04を使用しています。

4

2 に答える 2

1

親プロセスでは、次のことを行っています。

char* txt = NULL;
.....  
n = read(clntfd[0], &txt, 256);

txtが指すバッファ内のデータを読み取っていますが、バッファを割り当てていないため、これは正しくありません。あなたが見ているのは、未定義の振る舞いの現れです。

于 2012-10-08T19:24:37.863 に答える
1

コードにさまざまなコメントと修正を追加しました。これで、意図したとおりに機能します。あなたの主な問題は、あなたがバッファを割り当てなかったというcodeaddictによって指摘されたようにでした。あなたがSIGSEGVでクラッシュしなかったことに私は驚いた。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void errorMsg(char* msg)
{
    printf("\n%s\n", msg);
//  exit(0);
}

// move this into global space and make it const (non modifiable, easyer to debug)
const char text_to_send[] = "Anything that you want will not be considered no matter what you do!!";

int main()
{
    int servfd[2];
    int clntfd[2];
    int chldpid;    

    if(pipe(servfd) < 0)
        errorMsg("Unable to create server pipe.!!");
    if(pipe(clntfd) < 0)
        errorMsg("Unable to create client pipe.!!!");

    if((chldpid = fork()) == 0)
    {
        char txt[256]; // You have to actually allocate a buffer (aka enough memory to hold your string. You have allocated a pointer to a buffer, but no actual buffer)
        close(servfd[1]);
        close(clntfd[0]);
        printf("@Client: Enter a string: ");

        scanf("%s", txt); // since you now actually have a buffer to put the input into this no longer fails

        printf("Entered.!!\n");
        int n;
        char txt1[256];
        write(clntfd[1], text_to_send, sizeof(text_to_send)); // write only as much as you actually have to say, not the whole size of your buffer

        while((n = read(servfd[0], txt1, 256)) > 0)
            printf("\nAt client: %d bytes read\n\tString: %s\n", n, txt1);

        // this is not nessesary at this point, but it is good style to clean up after yourself
        close(servfd[0]);
        close(clntfd[1]);
    }
    else    
    {
        //printf("Parent:   \n\n");
        close(servfd[0]);
        close(clntfd[1]);
        char txt[256]; // same here, you need to actually allocate a buffer.
        int n, n1;  
        n = read(clntfd[0], txt, 256); // read into txt, not &txt. you want to read into your buffer pointed to by txt, not into the part of memory that contains the pointer
        printf("Server read: %d\n", n);
        n1 = write(servfd[1], txt, n); // do not send the whole buffer, just as much as you have actually useful information in it
        printf("Server write: %d\n", n1);

        // close the loose file descriptors, else your child will read on them forever
        close(servfd[1]);
        close(clntfd[0]);

        int status;
        wait(&status); // this is called like this. if you want to use the pid you call waitpid(chldpid, &status, 0);
    }
    exit(0);            
}
于 2012-10-08T20:02:00.310 に答える