这里我尝试使用管道创建一个简单的客户端和服务器。我分叉一个进程,让孩子充当客户端,父亲充当服务器。以下是代码:
#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);
}
这就是发生的事情。当我运行该程序时,它只打印Anything that yo
(恰好是16个字符),而不是其他内容。当我试图使用评论中显示的txt1
循环查看for
的完整内容时,我发现在yo
txt1
之后有{null}值(天知道从哪里开始) }。之后它们应该是正常的内容。知道为什么会这样吗?
当我尝试在适当的位置打印它们时,读取和写入的字节数都是正确的。它打印256 bytes read
。但是,strlen的txt1
大小为'16'。此外,程序在打印部分字符串后挂起。
当我尝试使用注释中显示的scanf
或fgets
从用户处获取字符串时,程序会在我按下回车后立即终止。对于为什么会发生这种情况也没有任何线索。
对行为的任何见解都会有所帮助。很抱歉有多个问题。谢谢你的时间。!我正在使用ubuntu 12.04,如果这可能有任何帮助。
答案 0 :(得分:1)
在您正在执行的父进程中:
char* txt = NULL;
.....
n = read(clntfd[0], &txt, 256);
这是不正确的,因为您正在读取txt
指向的缓冲区中的数据,但您没有分配缓冲区!!你所看到的是未定义行为的表现。
答案 1 :(得分: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);
}