Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中使用管道创建客户端和服务器时的奇怪行为_C_Linux_Ubuntu_Client Server_Pipe - Fatal编程技术网

在C中使用管道创建客户端和服务器时的奇怪行为

在C中使用管道创建客户端和服务器时的奇怪行为,c,linux,ubuntu,client-server,pipe,C,Linux,Ubuntu,Client Server,Pipe,在这里,我尝试使用管道创建一个简单的客户端和服务器。我分叉一个进程,使子进程充当客户机,父进程充当服务器。代码如下: #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()

在这里,我尝试使用管道创建一个简单的客户端和服务器。我分叉一个进程,使子进程充当客户机,父进程充当服务器。代码如下:

#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);            
}
#包括
#包括
#包括
#包括
无效错误消息(字符*消息)
{
printf(“\n%s\n”,msg);
//出口(0);
}
int main()
{
int-servfd[2];
int-clntfd[2];
int-chldpid;
如果(管道(servfd)<0)
errorMsg(“无法创建服务器管道!!”;
如果(管道(clntfd)<0)
errorMsg(“无法创建客户端管道!!!);
如果((chldpid=fork())==0)
{
char*txt=(char*)calloc(256,sizeof(char));
关闭(servfd[1]);
关闭(clntfd[0]);
printf(“@Client:输入字符串:”);
//scanf(“%s”,txt);//或fgets
printf(“已输入”。!!);
int n;
txt=“无论你做什么,你想要的任何东西都不会被考虑!!”;
字符txt1[256];
写入(clntfd[1],txt,256);
//如果(txt1[strlen(txt1)-1]='\n')
//{printf(“asdasdas”);
//txt[strlen(txt)-1]='\0';}
//int i=0;
//对于(i=0;i<256;i++)
//printf(“%c”,txt1[i]);
而((n=read(servfd[0],txt1,256))>0)
printf(“\n客户端:%d字节读取\n\t字符串:%s\n”,n,txt1);
}
其他的
{
//printf(“父项:\n\n”);
关闭(servfd[0]);
关闭(clntfd[1]);
char*txt=NULL;
int n,n1;
n=读取(clntfd[0],&txt,256);
printf(“服务器读取:%d”,n);
n1=写入(servfd[1],&txt,256);
printf(“服务器写入:%d”,n1);
等待(chldpid);
}
出口(0);
}
问题1: 这就是正在发生的事情。当我运行这个程序时,它只打印任何你想要的东西(正好16个字符),其他什么都不打印。当我试图使用注释中显示的
for
循环查看
txt1
的完整内容时,我发现
txt1
yo
之后有空值(天知道从哪里来)。之后是正常的内容,因为他们应该。知道为什么会这样吗

编辑: 当我尝试在适当的位置打印它们时,读取和写入的字节数都是正确的。它打印读取的
256字节
。然而,斯特伦的
txt1
的大小是“16”。此外,程序在打印部分字符串后挂起

问题2: 当我尝试使用注释中显示的
scanf
fgets
从用户处获取字符串时,程序会在我按enter键时立即终止。也不知道为什么会这样


对这些行为的任何洞察都会有所帮助。对不起,有很多问题。谢谢你的时间。!我正在使用Ubuntu12.04,如果这有什么帮助的话。

在您正在执行的父进程中:

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

这是不正确的,因为您正在读取由
txt
指向的缓冲区中的数据,但您尚未分配缓冲区!!你所看到的是一种未定义行为的表现

我已经为您的代码添加了各种注释和更正。它现在按预期工作。 正如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);            
}
#包括
#包括
#包括
#包括
无效错误消息(字符*消息)
{
printf(“\n%s\n”,msg);
//出口(0);
}
//将其移动到全局空间并使其恒定(不可修改,易于调试)
const char text_to_send[]=“无论你做什么,你想要的任何东西都不会被考虑!!”;
int main()
{
int-servfd[2];
int-clntfd[2];
int-chldpid;
如果(管道(servfd)<0)
errorMsg(“无法创建服务器管道!!”;
如果(管道(clntfd)<0)
errorMsg(“无法创建客户端管道!!!);
如果((chldpid=fork())==0)
{
char txt[256];//您必须实际分配一个缓冲区(亦称足够的内存来容纳字符串。您已经分配了一个指向缓冲区的指针,但没有实际的缓冲区)
关闭(servfd[1]);
关闭(clntfd[0]);
printf(“@Client:输入字符串:”);
scanf(“%s”,txt);//因为您现在实际上有了一个缓冲区,可以将输入放入其中,所以不再失败
printf(“已输入”。!!\n”);
int n;
字符txt1[256];
write(clntfd[1],text_to_send,sizeof(text_to_send));//只写实际需要写的内容,而不是整个缓冲区的大小
而((n=read(servfd[0],txt1,256))>0)
printf(“\n客户端:%d字节读取\n\t字符串:%s\n”,n,txt1);
//在这一点上,这不是必须的,但这是一个很好的方式来清理后,你自己
关闭(servfd[0]);
关闭(clntfd[1]);
}
其他的
{
//printf(“父项:\n\n”);
关闭(servfd[0]);
关闭(clntfd[1]);
char txt[256];//这里也是一样,您需要实际分配一个缓冲区。
int n,n1;
n=read(clntfd[0],txt,256);//读入txt,而不是&txt。您希望读入由txt指向的缓冲区,而不是读入包含指针的内存部分
printf(“服务器读取:%d\n”,n);
n1=write(servfd[1],txt,n);//不要发送整个缓冲区,因为其中包含实际有用的信息
printf(“服务器写入:%d\n”,n1);
//关闭松散的文件描述符,否则您的孩子将永远阅读它们
关闭(servfd[1]);
关闭(clntfd[0]);
智力状态;
wait(&status);//这是这样调用的。如果要使用pid,请调用waitpid(chldpid,&status,0);
}
出口(0);
}

不要忘记在相关位置调用
fflush(NULL)
,例如在
printf
之后和
read
调用之前。尝试过,但没有效果。只需使用
char txt[256]在孩子身上…是的,你是对的。但即使在我做了一个
malloc
之后,在