linux下实现两人、三人无序对话功能

时间:2022-01-27 11:25:59

序:引子

对话功能实际上就是利用管道见得通信。最原始的是一方发另一方收,不能进项交互,发送方的代码如下:

 /*============================================
> Copyright (C) 2014 All rights reserved.
> FileName:send.c
> author:donald
> details:
==============================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define N 1024
int main(int argc, const char *argv[])
{ if(- == mkfifo(argv[],)){//creat 2
perror("failed");
exit(-);
} printf("mkfifo over!\n");
int fd_send,fd_recev;
printf("open fifo...\n"); fd_send = open(argv[],O_WRONLY); if(fd_send == -){//必须另一方打开
perror("open failed");
unlink(argv[]);
exit(-);
}
printf("open success!\n"); char send_buf[N];
while(memset(send_buf,,N),fgets(send_buf,N,stdin) != NULL){
write(fd_send,send_buf,strlen(send_buf));
} printf("send over\n");
unlink(argv[]);
return ;
}

send.c

接收方的代码:

 /*============================================
> Copyright (C) 2014 All rights reserved.
> FileName:recv.c
> author:donald
> details:
==============================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define N 1024
int main(int argc, const char *argv[])
{
int fd_send,fd_recev;
printf("open fifo...\n");
fd_recev = open(argv[],O_RDONLY); if(fd_send == -){
perror("open failed");
unlink(argv[]);
exit(-);
}
printf("open success!\n"); char recev_buf[];
while(memset(recev_buf,,N),read(fd_recev,recev_buf,N) > ){
printf("%s",recev_buf);
} printf("recev over\n");
close(fd_recev);
unlink(argv[]);
return ;
}

recev.c

两人回话

对于两个程序之间的进行交互式对话有两种方式:

A.一问一答式,这是最简单的方式,但也是最不人性化的方法,运行后你就会产生一种回到上个世纪的错觉

B.没有固定的顺序,和QQ一样,想说就说,不用等到另一方说完一句才能说。

A方法比较简单,直接上代码:

启动方:

 /*============================================
> Copyright (C) 2014 All rights reserved.
> FileName:send.c
> author:donald
> date:2014/08/22/ 14:45:45
> details:
==============================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define N 1024
int main(int argc, const char *argv[])
{ if(- == mkfifo(argv[],)){//creat 1
perror("failed");
exit(-);
} printf("mkfifo over!\n");
int fd_send,fd_recev;
printf("open fifo...\n"); fd_send = open(argv[],O_WRONLY); if(fd_send == -){//必须另一方打开
perror("open failed");
unlink(argv[]);
// exit(-1);
}
printf("open success!\n"); char send_buf[N];
while(memset(send_buf,,N),fgets(send_buf,N,stdin) != NULL){
write(fd_send,send_buf,strlen(send_buf));
} printf("send over\n");
unlink(argv[]);
return ;
}

send.c

recev_send.c

B方法利用创建一个进程(fork)来实现交互,其代码为:

 /*===========================================
> Copyright (C)2014All rights reserved
> File Name: fork_re_se.c
> Author: Donald
=============================================*/ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define N 1024
int main(int argc, const char *argv[])
{
#if 1
if(- == mkfifo(argv[],)){
perror("failed");
exit(-);
}
printf("mkfifo over!\n");
#endif
int fd_send,fd_recev;
printf("open fifo...\n");
fd_recev = open(argv[],O_RDONLY);
fd_send = open(argv[],O_WRONLY); if(fd_send == - || fd_recev == -){
perror("open failed");
unlink(argv[]);
exit(-);
}
printf("open success!\n"); char recev_buf[];
char send_buf[N];
if(fork() == ){//child recev
close(fd_send);
//while(memset(recev_buf,0,N),read(fd_recev,recev_buf,strlen(recev_buf)) != 0){这里不能用strlen(recev_buf在while中进行了初始化,所以长度为0)
while(memset(recev_buf,,N),read(fd_recev,recev_buf,N) != ){
//write(1,recev_buf,N);
printf("%s",recev_buf);
}
exit();
}else{//parent send
close(fd_recev);
while(memset(send_buf,,N),fgets(send_buf,N,stdin) != NULL){
write(fd_send,send_buf,strlen(send_buf));
}
close(fd_send);
wait(NULL);
unlink(argv[]);
}
printf("recev over\n");
return ;
}

fork_re_se.c

 /*===========================================
> Copyright (C)2014All rights reserved
> File Name: fork_se_re.c
> Author: Donald
=============================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define N 1024
int main(int argc, const char *argv[])
{
#if 1
if(- == mkfifo(argv[],)){
perror("failed");
exit(-);
}
printf("mkfifo over!\n");
#endif
int fd_send,fd_recev;
printf("open fifo...\n");
fd_send = open(argv[],O_WRONLY);
fd_recev = open(argv[],O_RDONLY); if(fd_send == - || fd_recev == -){
perror("open failed");
unlink(argv[]);
exit(-);
}
printf("open success!\n"); char recev_buf[];
char send_buf[N];
if(fork() == ){//child recev
close(fd_send);
while(memset(recev_buf,,N),read(fd_recev,recev_buf,N) != ){
//write(1,recev_buf,N);
printf("%s",recev_buf);
}
exit();
}else{//parent send
close(fd_recev);
while(memset(send_buf,,N),fgets(send_buf,N,stdin) != NULL){
write(fd_send,send_buf,strlen(send_buf));
}
close(fd_send);
wait(NULL);
unlink(argv[]);
} printf("send over\n");
return ;
}

fork_se_re.c

三人无序对话

本程序主要通过父进程创建两个子进程,通过管道来实现,和两人无序对话的功能一样。只要逻辑清晰,并不难。共需要pipe(有名管道)六根,功能为用于读、写,为了使逻辑清晰,方便讨论,以下1、2、3分别代表程序1、2、3之间的管道,分别对程序之间的管道进项讨论分析:

A B C
1-2 write 1-2 read 1-3 read
1-3 write 2-1 write 3-1 write
2-1 read 2-3 write 2-3 read
3-1 read 3-2 read 3-2 write
 以上表格表示的具体含义我在这里举例说明一下。eg:对于A(聊天猪头)而言共有四根管道与其相连,两根用于读,另外两根用于写,1-2管道代表A、B之间的管道A需要进行写操作,而B进行读操作。 
  • A:第一人
 /*============================================
> Copyright (C) 2014 All rights reserved.
> FileName:1.c
> author:donald
> date:2014/08/22/ 20:28:53
> details:
==============================================*/ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define N 1024
int main(int argc, const char *argv[])//12,13,21,31
{
if(mkfifo(argv[],) == - || mkfifo(argv[],) == -){
perror("mkfifo");
exit();
} int fd_12,fd_13,fd_21,fd_31;
char buf[N];
fd_12 = open(argv[],O_WRONLY);
fd_13 = open(argv[],O_WRONLY);
fd_21 = open(argv[],O_RDONLY);
fd_31 = open(argv[],O_RDONLY); printf("open sucess\n"); if(fork() == ){//21 r
close(fd_13);
close(fd_12);
close(fd_31);
while(memset(buf,,N),read(fd_21,buf,N) != ){
printf("from 2:");
write(,buf,strlen(buf));
}
close(fd_21);
exit();
}
if(fork() == ){//31 r
close(fd_13);
close(fd_12);
close(fd_21);
while(memset(buf,,N),read(fd_31,buf,N) != ){
printf("from 3:");
write(,buf,strlen(buf));
}
close(fd_31);
exit();
} //12 13 w
close(fd_21);
close(fd_31);
while(memset(buf,,N),fgets(buf,N,stdin) != NULL){
write(fd_13,buf,strlen(buf));
write(fd_12,buf,strlen(buf));
}
close(fd_13);
close(fd_12);
wait(NULL);
wait(NULL); unlink(argv[]);
unlink(argv[]);
printf("program 1 over\n");
return ;
}

1.c

  • B:第二人
 /*============================================
> Copyright (C) 2014 All rights reserved.
> FileName:2.c
> author:donald
> date:2014/08/22/ 20:29:02
> details:
==============================================*/ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define N 1024
int main(int argc, const char *argv[])
{ if(mkfifo(argv[],) == - || mkfifo(argv[],) == -){
perror("mkfifo");
exit();
} int fd_12,fd_21,fd_23,fd_32;
char buf[N];
fd_12 = open(argv[],O_RDONLY);
fd_21 = open(argv[],O_WRONLY);
fd_23 = open(argv[],O_WRONLY);
fd_32 = open(argv[],O_RDONLY); printf("open success\n"); if(fork() == ){//12 r
close(fd_32);
close(fd_21);
close(fd_23);
while(memset(buf,,N),read(fd_12,buf,N) != ){
printf("from 1:");
write(,buf,strlen(buf));
}
close(fd_12);
exit();
} if(fork() == ){//32 r
close(fd_12);
close(fd_21);
close(fd_23);
while(memset(buf,,N),read(fd_32,buf,N) != ){
printf("from 3:");
write(,buf,strlen(buf));
}
close(fd_32);
exit();
} //21 23 w
close(fd_12);
close(fd_32);
while(memset(buf,,N),fgets(buf,N,stdin) != NULL){
write(fd_21,buf,strlen(buf));
write(fd_23,buf,strlen(buf));
}
close(fd_21);
close(fd_23);
wait(NULL);
wait(NULL); unlink(argv[]);
unlink(argv[]);
printf("program 2 over\n");
return ;
}

2.c

  • C:第三人
 /*============================================
> Copyright (C) 2014 All rights reserved.
> FileName:3.c
> author:donald
> date:2014/08/22/ 20:29:13
> details:
==============================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define N 1024
int main(int argc, const char *argv[])
{ if(mkfifo(argv[],) == - || mkfifo(argv[],) == -){
perror("mkfifo");
exit();
} int fd_13,fd_31,fd_23,fd_32;
char buf[N];
fd_13 = open(argv[],O_RDONLY);
fd_31 = open(argv[],O_WRONLY);
fd_23 = open(argv[],O_RDONLY);
fd_32 = open(argv[],O_WRONLY); printf("open success\n"); if(fork() == ){//13 r
close(fd_31);
close(fd_23);
close(fd_32);
while(memset(buf,,N),read(fd_13,buf,N) != ){
printf("from 1:");
write(,buf,strlen(buf));
}
close(fd_13);
exit();
}
if(fork() == ){//23 r
close(fd_13);
close(fd_31);
close(fd_32);
while(memset(buf,,N),read(fd_23,buf,N) != ){
printf("from 2:");
write(,buf,strlen(buf));
}
close(fd_23);
exit();
} //31 32 w
close(fd_13);
close(fd_23);
while(memset(buf,,N),fgets(buf,N,stdin) != NULL){
write(fd_31,buf,strlen(buf));
write(fd_32,buf,strlen(buf));
}
close(fd_31);
close(fd_32);
wait(NULL);
wait(NULL); unlink(argv[]);
unlink(argv[]);
printf("program 3 over\n");
return ;
}

3.c

PS:在命令行参数中还需注意的,假设1.c、2.c、3.c的可执行文件为A.out、B.out、C.out。命令行参数分别为:(其实和表格里分析的一样)

            1. ./A.out   12.fifo  13.fifo  21.fifo   31.fifo
            2. ./B.out   12.fifo  21.fifo  23.fifo   32.fifo
            3. ./C.out   13.fifo  31.fifo  23.fifo   32.fifo

三人以上的用fork就没必要了,需要另寻方,一般采用服务器的处理方式。