【实验九】Linux的命名管道编程

目录

一、问题

二、代码

1、serMain.cpp

2、server.h

3、server.cpp

4、cliMain.cpp

5、client.h

6、client.cpp 

7、message.h

8、message.cpp

9.filo.mk

三、运行结果


一、问题

客户端输入数字运算,服务端计算返回结果给客服端,客户端显示结果。

函数参考博客

匿名管道和命名管道的区别:
(1)匿名管道由pipe函数创建并打开。
(2)命名管道由mkfifo函数创建,打开用open
(3)FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。 

二、代码

1、serMain.cpp

#include<unistd.h>
#include"server.h"
int main(int argc,char*argv[]){
	unlink(argv[1]);
	server(argv[1],argv[2]);
	return 0;
}

2、server.h

void server(const char*ser,const char*cli);

3、server.cpp

#include<iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include"server.h"
#include"message.h"

void handle_mes(Message& m){
	switch(m.op){
		case 0:
			m.res=m.oprand1+m.oprand2;
			break;
		case 1:
			m.res=m.oprand1-m.oprand2;
			break;
		case 2:
			m.res=m.oprand1*m.oprand2;
			break;
		case 3: 
			if(m.oprand2!=0){
				m.res=m.oprand1/m.oprand2;
			}else{
				m.status='F';
			}
			break;
		default:
			m.status='N';
			break;
	}
}
void process(const int rfd,const int wfd){
	while(true){
		Message m;
		memset(&m,0,sizeof(m));
		int len=read(rfd,&m,sizeof(m));
		if(len<= 0){
			std::cerr<<"client close\n";
			break;
		}
		handle_mes(m);
		write(wfd,&m,sizeof(m));
		
	}
}
void server(const char*ser,const char*cli){
	int rfd,wfd;
	do{
		if(mkfifo(ser,0664)==-1){
			std::cerr<<"mkfifo wrong\n";
			break;
		}
		rfd=open(ser,O_RDONLY);
		if(rfd == -1){
			std::cerr<<"open wrong\n";
			break;
		}
		wfd=open(cli,O_WRONLY);
		if(wfd == -1){
			std::cerr<<"open wrong\n";
			break;
		}

		process(rfd,wfd);
	}while(0);
	close(rfd);
    close(wfd);
}

4、cliMain.cpp

#include<unistd.h>
#include"client.h"
int main(int argc,char*argv[]){
	unlink(argv[2]);
	client(argv[1],argv[2]);
	return 0;
}

5、client.h

void client(const char*ser,const char*cli);

6、client.cpp 

#include<iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include"client.h"
#include"message.h"
void process(const int rfd ,const int wfd){
	while(true){
		Message m;
		memset(&m,0,sizeof(m));
		std::cin>>m;
		if(std::cin.eof()) break;
		m.status='S';
		write(wfd,&m,sizeof(m));
		read(rfd,&m,sizeof(m));
		std::cout<<m<<std::endl;
	}
}
void client(const char* ser,const char*cli){
	int wfd,rfd;
	do{
		if(mkfifo(cli,0664) == -1){
			std::cerr<<"mkfio wrong\n";
			break;
		
		}
		wfd=open(ser,O_WRONLY);
		if(wfd == -1){
		      	std::cerr<<"open wrong\n";
			break;
		}
		rfd=open(cli,O_RDONLY);
		if(rfd == -1){
		      	std::cerr<<"open wrong\n";
			break;
		}
		process(rfd,wfd);
	}while(0);
	close(wfd);
    close(rfd);
}

7、message.h

#include<iostream>
struct Message{
	int oprand1;
	int op;
	int oprand2;
	int res;
	char status;
};

std::istream& operator >>(std::istream& in,Message& m);
std::ostream& operator <<(std::ostream& out,const Message& m);

8、message.cpp

#include"message.h"

std::istream& operator >>(std::istream& in,Message& m) {
	in>>m.oprand1>>m.op>>m.oprand2;
	return in;
}

std::ostream& operator <<(std::ostream& out,const Message& m){
	if(m.status=='S'){
	out<<m.oprand1<<" "<<m.op<<" "<<m.oprand2<<"="<<m.res;
	}else if(m.status=='N'){
		out<<"operator input error";
	}else if(m.status=='F'){
		out<<"divior is 0";
	}
	return out;
}

9.filo.mk

GCC=g++
CFLAG=-c
OFLAG=-o
SEXE=serMain
SOBJ=serMain.o server.o
CEXE=cliMain
COBJ=cliMain.o client.o message.o
all:${SEXE} ${CEXE}
${SEXE}:${SOBJ}
        ${GCC} ${OFLAG} $@ $^
${CEXE}:${COBJ}
        ${GCC} ${OFLAG} $@ $^
%.o:%.cpp
        ${GCC} ${CFLAG} $^
clean:    
        rm *.o

 信息由加减乘除登录账号和密码,只需修改以下几个地方。

server.cpp

const char ifname[]="login.txt";
void han_mes(Message& m){
	std::ifstream fin(ifname);
	std::string user;
	std::string password;
        while(fin>>user>>password){
	if(user==m.user&&password==m.password){
		m.status='S';
	}else{
		m.status='N';
	}
	}
	fin.close();
	
}

message.h 

#include<iostream>
#include<string.h>
struct Message{

	char user[10];
	char password[10];
	char status;
};

std::istream &operator >>(std::istream& in, Message& m);
std::ostream &operator <<(std::ostream& out,const Message& m);

message.cpp 

#include"message.h"

std::istream& operator >>(std::istream& in,Message& m) {
	in>>m.user>>m.password;
	return in;
}

std::ostream& operator <<(std::ostream& out,const Message& m){
	if(m.status=='S'){
	out<<"login sucessful";
	}else if(m.status=='N'){
		out<<"login error";
	}	
	return out;
}

三、运行结果

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
进程间通信是指在不同进程之间进行数据交换和同步的一种技术。Linux提供了多种进程间通信的方式,包括管道、消息队列、共享内存和信号量等。在实验六中,我们将学习如何使用这些方式进行进程间通信。 1. 管道 管道是一种半双工的通信方式,它可以在两个进程之间传递数据。在Linux中,管道分为匿名管道命名管道。匿名管道只能用于父子进程之间的通信,而命名管道可以用于任意两个进程之间的通信。 使用匿名管道进行进程间通信的步骤如下: - 父进程创建管道,并调用fork函数创建子进程。 - 子进程通过管道接收数据。 - 父进程通过管道发送数据。 - 子进程接收到数据后进行处理。 使用命名管道进行进程间通信的步骤如下: - 创建命名管道。 - 打开命名管道并进行读写操作。 2. 消息队列 消息队列是一种进程间通信机制,它允许不同进程之间通过一个消息传递序列来进行通信。在Linux中,每个消息都有一个类型,接收进程可以选择接收某个特定类型的消息。 使用消息队列进行进程间通信的步骤如下: - 创建消息队列。 - 发送消息到消息队列。 - 接收消息并进行处理。 3. 共享内存 共享内存是一种进程间通信的方式,它允许不同进程之间共享同一个物理内存区域。这种方式比较高效,但需要考虑进程间的同步和互斥问题,否则会出现数据不一致的情况。 使用共享内存进行进程间通信的步骤如下: - 创建共享内存区域。 - 进程通过共享内存区域进行数据交换。 - 进程需要进行同步和互斥操作。 4. 信号量 信号量是一种进程间同步的机制,它可以用来保证不同进程之间的共享资源在同一时刻只能被一个进程访问。在Linux中,每个信号量都有一个计数器,当计数器为0时,进程需要等待;当计数器大于0时,进程可以继续执行。 使用信号量进行进程间通信的步骤如下: - 创建信号量。 - 进程对信号量进行P操作(等待)。 - 进程对信号量进行V操作(释放)。 总体来说,不同的进程间通信方式各有优缺点,应根据实际需求选择适合的方式。在实验六中,我们将通过编写代码来学习如何使用这些方式进行进程间通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值