我用叉子和烟斗模拟了呼叫者和接收者之间的对话。父进程是接收方,子进程是调用方。每条消息都以换行符结束。
这个程序似乎运行正常。我还需要照顾其他的情况吗?
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#define BUF_LEN 512
#define READ_END 0
#define WRITE_END 1
int main()
{
int fd[2];
if (pipe(fd) == -1) {
fprintf(stderr, "Pipe failed");
return 1;
}
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed");
return 1;
}
// the parent process is the receiver
if (pid > 0) {
close(fd[WRITE_END]);
char buffer[BUF_LEN + 1] = "";
bool end_call = false;
do {
// strcpy(buffer, "");
if (read(fd[READ_END], buffer, sizeof buffer) != 0) {
// char *start = buffer;
char msg[BUF_LEN + 1] = "";
char *end = buffer;
int i = strlen(msg);
while (*end) {
msg[i++] = *(end++);
msg[i] = '\0';
if (msg[strlen(msg) - 1] == '\n') {
printf("Receiver: Received %s", msg);
if (!strcmp(msg, "Bye!\n")) {
end_call = true;
}
strcpy(msg, "");
i = strlen(msg);
}
}
// if (strcmp(buffer, "")) {
// printf("Received %s", buffer);
// }
}
} while (!end_call);
close(fd[READ_END]);
} else {
close(fd[READ_END]);
// const char *msg = "Hello";
char buffer[BUF_LEN + 1] = "";
bool end_call = false;
printf("Caller: Enter messages to be sent to the receiver."
"(\"Bye!\" to end call)\n");
do {
// printf("Caller: ");
fgets(buffer, sizeof buffer, stdin);
if (!strcmp(buffer, "Bye!\n")) {
end_call = true;
}
// printf("Sent %s\n", buffer);
write(fd[WRITE_END], buffer, strlen(buffer) + 1);
} while (!end_call);
close(fd[WRITE_END]);
}
return 0;
}发布于 2016-10-25 03:12:27
的调用
让我们在这个代码块中计算对strlen()的调用:
if (read(fd[READ\_END], buffer, sizeof buffer) != 0) { // char \*start = buffer; char msg[BUF\_LEN + 1] = ""; char \*end = buffer; int i = strlen(msg); while (\*end) { msg[i++] = \*(end++); msg[i] = '\0'; if (msg[strlen(msg) - 1] == '\n') { printf("Receiver: Received %s", msg); if (!strcmp(msg, "Bye!\n")) { end\_call = true; } strcpy(msg, ""); i = strlen(msg); } } // if (strcmp(buffer, "")) { // printf("Received %s", buffer); // } }
msg仍然是空的。因此,这一行可以用i = 0代替。msg[i-1]添加了这个字符,所以不需要调用strlen()。msg设置为""之后。所以你知道这里的长度是零。您也不需要调用strcpy()仅仅是为了清除msg。修改后的代码为零调用strlen()和strcpy(),如下所示:
if (read(fd[READ_END], buffer, sizeof buffer) != 0) {
char msg[BUF_LEN + 1] = "";
char *end = buffer;
int i = 0;
while (*end) {
msg[i++] = *(end++);
msg[i] = '\0';
if (msg[i - 1] == '\n') {
printf("Receiver: Received %s", msg);
if (!strcmp(msg, "Bye!\n")) {
end_call = true;
}
msg[0] = '\0';
i = 0;
}
}
}在实际程序中,由于您同时控制客户端和服务器,因此没有实际的缓冲区溢出。但是,如果只查看服务器部分,就会发现一个潜在的问题:
char buffer[BUF\_LEN + 1] = ""; if (read(fd[READ\_END], buffer, sizeof buffer) != 0) {
在这里,使用read调用sizeof buffer,这意味着它可以填充整个缓冲区,而不需要终止空字符。
然后,使用以下内容迭代缓冲区:
char \*end = buffer; while (\*end) {
这意味着,如果没有空终止字符,您将读取缓冲区的末尾。
看起来,您将缓冲区大小调整为BUF_LEN + 1是有原因的(为一个确定的空字符留出空间),所以您应该只调用一个长度较短的read():
if (read(fd[READ_END], buffer, sizeof(buffer)-1) != 0) {发布于 2016-10-25 03:19:18
read返回-1,一旦发生错误,它很可能会继续返回-1,使接收器陷入无限循环。我建议int rc;while ((rc =read(.)> 0) {do_receiver_logic(.);} if (rc == 0) { handle_peer_close();}handle_read_error()}您可能希望特别注意瞬态错误,但我宁愿尝试重新连接。"Bye"关闭了流,那么发送方注定要永远重复发送最后一个字符串。至少,测试fgets返回的不是NULL。https://codereview.stackexchange.com/questions/145153
复制相似问题