这个是我在上linux高级环境编程的课程的作业,自己觉得写的还不错,拿出来跟大家分享哈
首先是开发环境截图,ubuntu vmware secureCRT
运行效果截图
源代码,有兴趣的可以拿去研究,贡献给大家。
mtimerServer.h
#ifndef __MTIMERSERVER_H
#define __MTIMERSERVER_H
#include <stdlib.h>
struct Requester
{
int interTimeSeconds;
int curTimeSeconds;
pid_t pid;
};
// 客户端发送的
struct RequestPKG
{
short type;
int interTimeSeconds;
pid_t pid;
};
#endif
mtimerServer.cpp
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <iostream>
#include "mtimerServer.h"
#define FIFO_INDEX 1
#define FIFO_PERMS (S_IRWXU | S_IWGRP| S_IWOTH)
#define REQESTNUM 10
using namespace std;
int main(int argc, char *argv[])
{
int readfd, readLen = 0;
char buff[12];
// 请求者队列
Requester rquser[REQESTNUM];
int rqusernum = 0;
// 请求者包信息
RequestPKG *rqpkg; int pkglen;
pkglen = sizeof(RequestPKG);
rqpkg = (RequestPKG *)malloc(pkglen);
if(argc != 2)
{
cout<<"Usage:"<<argv[0]<<" fifoname"<<endl;
return 1;
}
cout<<"start mkfifo"<<endl;
if((mkfifo(argv[FIFO_INDEX], FIFO_PERMS) == -1)
&&(errno != EEXIST))
{
perror("Server failed to create fifo");
return -1;
}
cout<<"start open"<<endl;
if((readfd = open(argv[FIFO_INDEX],O_RDONLY|O_NONBLOCK)) == -1)
{
perror("Server failed to open fifo");
return -1;
}
// 从管道非阻塞读取数据
cout<<"start to read noblock:"<<readfd<<endl;
while(1)
{
// read 是非阻塞的函数了
if((readLen = read(readfd, rqpkg, pkglen)) < 0)
{
if(errno == EAGAIN)
{
cout<<"No data yet!"<<endl;
}
else
perror("read error");
}
else if(readLen > 0)
{
// 有新的请求者加入队列, 若已经加入过,则跳过
if(rqpkg->type == 1)
{
if(rqusernum < REQESTNUM)
{
int rpid = rqpkg->pid;
bool isInqueue = false;
for(int i=0; i<rqusernum; i++)
{
Requester temp = rquser[i];
if(rpid == temp.pid)
{
isInqueue = true;
break;
}
}
if(!isInqueue) // 请求者入队
{
cout<<"read pipe timeinter:"<<rqpkg->interTimeSeconds<<", type:"<<rqpkg->type<<endl;
rquser[rqusernum].interTimeSeconds = rqpkg->interTimeSeconds;
rquser[rqusernum].pid = rqpkg->pid;
rquser[rqusernum].curTimeSeconds = 0;
rqusernum++;
}
}
else
{
cout<<"Queue is full"<<endl;
}
}
else if(rqpkg->type == 2) // 表明请求者退出了
{
int RQindex = 0;
for(int i=0; i<rqusernum; i++)
{
Requester temp = rquser[i];
if(rqpkg->pid == temp.pid)
{
RQindex = i;
break;
}
}
for(int i=RQindex+1; i<rqusernum; i++)
{
rquser[i-1] = rquser[i];
}
rqusernum--;
}
}
sleep(3);
// 遍历所有已经发送了定时的请求者
if(rqusernum > 0)
{
for(int i=0; i<rqusernum; i++)
{
cout<<rquser[i].interTimeSeconds<<",";
cout<<rquser[i].curTimeSeconds<<",";
cout<<rquser[i].pid<<endl;
// 让时间衰减,然后用kill信号通知请求者
if(rquser[i].curTimeSeconds < rquser[i].interTimeSeconds)
{
rquser[i].curTimeSeconds++;
}
else
{
cout<<"send kill singal"<<endl;
}
}
}
}
free(rqpkg);
close(readfd);
return 0;
}
mtimerClient.h
#ifndef __MTIMERSERVER_H
#define __MTIMERSERVER_H
#include <stdlib.h>
struct Requester
{
int interTimeSeconds;
int curTimeSeconds;
pid_t pid;
};
// 客户端发送的
struct RequestPKG
{
short type;
int interTimeSeconds;
pid_t pid;
};
#endif
mtimerClient.cpp
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <iostream>
#include "mtimerClient.h"
#define FIFO_INDEX 1
#define FIFO_PERMS (S_IRWXU | S_IWGRP| S_IWOTH)
using namespace std;
void sendDiscon(int fd, int seconds)
{
RequestPKG *rqpkg;
rqpkg = (RequestPKG *)malloc(sizeof(RequestPKG));
rqpkg->interTimeSeconds = seconds;
rqpkg->pid = getpid();
rqpkg->type = 2;
int writeByte = write(fd, rqpkg, sizeof(RequestPKG));
if(writeByte > 0)
{
cout<<"I am out normal"<<endl;
}
free(rqpkg);
}
int main(int argc, char *argv[])
{
int writefd, writeTimes = 0;
char buff[12] = "ABCDEFG";
int interSeconds = 5;
// 请求包
RequestPKG *rqpkg;
rqpkg = (RequestPKG *)malloc(sizeof(RequestPKG));
rqpkg->interTimeSeconds = interSeconds;
rqpkg->pid = getpid();
rqpkg->type = 1;
if(argc != 2)
{
cout<<"Usage:"<<argv[0]<<" fifoname"<<endl;
return 1;
}
cout<<"start open"<<endl;
if((writefd = open(argv[FIFO_INDEX], O_WRONLY|O_NONBLOCK)) == -1)
{
perror("Client failed to open fifo");
return -1;
}
// 从管道非阻塞读取数据
cout<<"start to read noblock"<<endl;
while(writeTimes < 6)
{
int writeByte = write(writefd, rqpkg, sizeof(RequestPKG));
if(writeByte < 0)
{
if(errno == EAGAIN)
cout<<"No read end !"<<endl;
else
perror("write error");
}
writeTimes++;
sleep(3);
}
/** 在这里需要添加一个信号处理的函数绑定
* 然后就可以做其他的任何事情,最后如果
* 要断开的话直接用(sendDiscon)断开
* 与定时器服务器的信号。
**/
sendDiscon(writefd, interSeconds);
free(rqpkg);
close(writefd);
return 0;
}