我的思路比较简单,具体总结如下:

1、服务器端启动,直接将所有文件上传至共享内存区

2、在服务器端本次共模拟两个文件,视频文件 1.mp4、图片1.jpg,两个文件各开辟一块过程内存区

3、文件资源名字通过映射发送至两端

4、客户端启动,通过文件名字自主选择要下载的文件资源

5、主函数中由父进程创建两个兄弟进程,由父进程发送自定义信号,指挥其子进程进行下载

这里总结一下我遇到的比较大的问题:

1、如果上传文本文件,在客户端获取文件大小比较简单,strlen()函数直接搞定,因为文本文件中存储的其实可以看成一个比较的字符串而已。

但是音视频以及图片类型的二进制文件,strlen()函数则无法运用,我也尝试了不少方法,例如循序判断字符,lseek等等,都无济于事。所这里我再次开辟了一块共享内存区存储文件的大小

2、如何通过父进程指挥其子进程去下载呢?

我是通过注册自定义信号SIGUSR1和SIGUSR2,然后通过kill(getpid(),执行函数)传递信号,去指挥子进程下载。

3、其他细微问题这里便不再赘述,都是一些变量未初始化、函数参数忘记使用、未删除映射区、未删除共享内存关联等等小问题。

废话不多说,上代码!

服务器端:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <error.h>
#include <string.h>
#include <time.h>
#include <signal.h>#define SHMKEY01 100//1.jpg的共享内存区
#define SHMKEY02 200//1.mp4的共享内存区
#define SHMKEY03 300//1.txt的共享内存区
#define SIZE 4096000int shmid,shmid02,shmid03;
char *buf = NULL;//共享内存1
char *buf02 = NULL;//共享内存2
int fp;//文件描述符1
int fp02;//文件描述符2
int fp03;//文件描述符3
int fd;//内存映射static int num01=0;
static int num02=0;typedef struct
{int n1;int n2;
}NUM;
NUM info[1];
NUM *buf03 = NULL;//共享内存3int main(int argc,char *argv[])
{printf("文件正在上传服务器,请稍后...\n");sleep(3);printf("文件上传成功!\n");shmid = shmget(SHMKEY01, SIZE, 0664 | IPC_CREAT);if(shmid==-1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid=%d\n",shmid);buf = (char *)shmat(shmid, NULL, 0);if(NULL == buf){perror("error");exit(1);}fp = open("/home/lianpan/0924/homework/1.jpg",O_RDONLY);//上传图片1.jpg             int ret01 = read(fp,buf,SIZE);printf("当前服务器获取到文件1.jpg共%d个字节\n",ret01);info[0].n1 = ret01;shmid02 = shmget(SHMKEY02, SIZE, 0664 | IPC_CREAT);if(shmid02 == -1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid02=%d\n",shmid02);buf02 = (char *)shmat(shmid02, NULL, 0);if(NULL == buf02){perror("error");exit(1);}fp02 = open("/home/lianpan/0924/homework/1.mp4",O_RDONLY);//上传视频1.mp4int ret02 = read(fp02,buf02,SIZE);printf("当前服务器获取到文件1.mp4共%d个字节\n",ret02);info[0].n2 = ret02;shmid03 = shmget(SHMKEY03, 4, 0664 | IPC_CREAT);if(shmid03 == -1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid03=%d\n",shmid03);buf03 = (NUM *)shmat(shmid03, NULL, 0);if(NULL == buf03){perror("error");exit(1);}*buf03 = info[0];fd = open("readme.txt",O_RDWR|O_CREAT,0664);//readme.txt文件映射到共享内存区if(-1 == fd){perror("内存映射失败");exit(-1);}int len = lseek(fd,0,SEEK_END);printf("当前服务器获取到文件readme.txt为%d个字节大小\n",len);system("ipcs -m");
//  printf("info[0].n1=%d,info[0].n2=%d\n",info[0].n1,info[0].n2);char *p = NULL;p = mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);//将文件映射到共享内存if(p == MAP_FAILED){perror("mmap error");exit(1);}
//  printf("文件read.txt的内容为:\n%s\n",p);munmap(p,len);//关闭映射区close(fp);//关闭文件描述符close(fp02);shmdt(buf);shmdt(buf02);sleep(15);return 0;
}

客户端:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <error.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <pthread.h>#define SHMKEY01 100//1.jpg的共享内存区
#define SHMKEY02 200//1.mp4的共享内存区
#define SHMKEY03 300//1.txt的共享内存区
#define SIZE 4096000int shmid,shmid02,shmid03;//共享内存返回值
int pid;//父子进程
char *buf = NULL;//共享内存1
char *buf02 = NULL;//共享内存2
//char *buf03 = NULL;//共享内存3
int fp;//文件描述符1
int fp02;//文件描述符2
int fp03;//文件描述符3
int fd;//内存映射
int len;//映射区内容大小
int num1 = 0;//接收文件大小
int num2 = 0;//接收文件大小typedef struct
{int n1;int n2;
}NUM;
NUM *buf03 = NULL;void client01()
{shmid = shmget(SHMKEY01, SIZE, 0);if(shmid==-1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid=%d\n",shmid);buf = (char *)shmat(shmid, NULL, 0);if(NULL == buf){perror("error");exit(1);}/*int mm=0;for(int j=0;;j++){if(*(buf+j) == EOF)break;else mm++;}printf("mm=%d\n",mm);int mmm = strlen(buf);printf("mmm=%d\n",mmm);*/fp = open("1.jpg",O_RDWR|O_CREAT,0777);int ret = write(fp,buf,num1);int n = lseek(fp,0,SEEK_END);printf("文件1.jpg的大小为:%d\n",n);if(ret == -1){perror("write error");exit(1);}elseprintf("由共享内存区buf写入到文件1.jpg大小为:%d\n",n);close(fp);//此时就可以关闭文件描述符
}void client02()
{shmid02 = shmget(SHMKEY02, SIZE, 0);if(shmid02 == -1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid02=%d\n",shmid02);buf02 = (char *)shmat(shmid02, NULL, 0);if(NULL == buf02){perror("error");exit(1);}fp02 = open("1.mp4",O_RDWR|O_CREAT,0777);      int ret = write(fp02,buf02,num2);int m = lseek(fp02,0,SEEK_END);printf("文件1.mp4的大小为:%d\n",m);if(ret == -1){perror("write error");exit(1);}elseprintf("由共享内存区buf02写入到文件2.txt大小为:%d\n",ret);close(fp02);
}void client03()
{shmid03 = shmget(SHMKEY03, 4, 0664 | IPC_CREAT);if(shmid03 == -1){printf("servre()...shmget() fail!\n");exit(1);}printf("server() shmid03=%d\n",shmid03);buf03 = (NUM *)shmat(shmid03, NULL, 0);if(NULL == buf03){perror("error");exit(1);}
//  printf("%d\n",buf03->n1);
//  printf("%d\n",buf03->n2);  }//内存映射
void mmaptest(void)
{fd = open("../readme.txt",O_RDWR|O_CREAT,0664);//readme.txt文件映射到共享内存区if(-1 == fd){perror("内存映射失败");exit(-1);}int len = lseek(fd,0,SEEK_END);
//  printf("当前获取到文件readme.txt为%d个字节大小\n",len);char *p = NULL;p = mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);//将文件映射到共享内存if(p == MAP_FAILED){perror("mmap error");exit(1);}
//  printf("文件readme.txt的内容为:\n%s\n",p);
}int main(int argc,char *argv[])
{client03();//内存共享获取文件大小num1 = buf03->n1;//结构体元素赋值全局变量num2 = buf03->n2;
//  printf("%d\n",num1);
//  printf("%d\n",num2);  char ch;int SHMKEY04 = 400;shmid03 = shmget(SHMKEY04,4,IPC_CREAT | 0777);if(shmid03 == -1){printf("main...shmget() fail!\n");exit(1);}printf("创建共享内存成功 shmid03=%d\n",shmid03);int *p = NULL;int j=0;p = (int *)shmat(shmid03,NULL,0);*p = 1;signal(SIGUSR1,client01);//注册自定义信号1signal(SIGUSR2,client02);//注册自定义信号2
//  signal(SIGUSR3,client02);mmaptest();printf("请选择您要下载的文件资源:\n1、1.jpg\n2、1.mp4\n");scanf("%c",&ch);switch(ch){case '1':pid = fork();if(pid == 0){printf("我是第一个子进程\n");if(*p == 1){printf("文件正在下载中,请等待...\n");static int n=6;for(int j=0;j<5;j++){printf("目前下载进程...%d%%\n",n);n += 13;usleep(500000);}printf("目前下载进程...100%%\n");printf("文件下载成功,请返回查看!\n");kill(getpid(),SIGUSR1);*p = 0;sleep(1);}}else if(pid > 0){//      printf("我是父进程\n");}break;case '2':pid = fork();if(pid == 0){printf("我是第二个子进程\n");static int n=7;if(*p == 1){printf("文件正在下载中,请等待...\n");for(int j=0;j<5;j++){printf("目前下载进程...%d%%\n",n);n += 13;usleep(500000);}printf("目前下载进程...100%%\n");printf("文件下载成功,请返回查看!\n");kill(getpid(),SIGUSR2);*p = 0;sleep(1);}}else if(pid > 0){//     printf("我是父进程\n");}break;default:break;}shmctl(shmid,IPC_RMID,0);//删除共享内存区shmctl(shmid02,IPC_RMID,0);shmctl(shmid03,IPC_RMID,0);munmap(p,len);//删除映射区return 0;
}

运行结果:

Linux系统下利用共享内存模拟迅雷下载相关推荐

  1. linux系统安装内存测试,一种Linux系统下基于IDK内存注错的测试方法及系统与流程...

    本发明涉及计算机服务器的 技术领域: :,具体涉及到一种Linux系统下基于IDK内存注错的测试方法及系统. 背景技术: ::在服务器领域中,内存是服务器中重要的部件之一,它是与CPU进行沟通的桥梁. ...

  2. Unix/Linux操作系统分析实验二 内存分配与回收:Linux系统下利用链表实现动态内存分配

    Unix/Linux操作系统分析实验一 进程控制与进程互斥 Unix/Linux操作系统分析实验三 文件操作算法: 实现在/proc目录下添加文件 Unix/Linux操作系统分析实验四 设备驱动: ...

  3. java 内存映射文件进程间通讯_[转]Windows环境下利用“共享内存”实现进程间通信的C/C++代码---利用CreateFileMapping和MapViewOfFile...

    进程间的通信方式有很多种, 上次我们说了最傻瓜的"共享外存/文件"的方法. 那么, 在本文中, 我们即将学习"共享内存"的方式实现进程间的通信, 这是IPC最快 ...

  4. linux系统下文件的上传和下载(rz、sz)

    linux系统下的rz.sz上传和下载 rz 是从本地上传文件的时候用的, sz 相当于把Linux 服务器上的文件 下载到 本地. 通过这两个命令就可以把 Windows 和Linux 的文件 进行 ...

  5. Linux系统编程—进程间通信—共享内存

    Linux共享内存 共享内存就是允许两个或多个进程共享一定的存储区.就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时候,其它进程都会察觉 ...

  6. Linux系统下利用Impost3r劫持sudo命令窃取凭据

    Impost3r是一款针对Linux平台的密码窃取工具,该工具采可以在linux系统的普通用户权限下制造水坑,从目标Linux主机中获取各类密码如ssh.su.sudo等. 软件使用 C 语言编写,可 ...

  7. opencv在linux系统下利用从cv2进行摄像头读取操作

    读取一直错误  根本没显示 ,后来查阅了好久发现是ubuntu中的摄像头褐诶主机的摄像头不匹配的问题, 来到主机,将主机中相机权限打开,进行共享,再回到ubuntu进行cheese命令检验,终于实现视 ...

  8. Unix/Linux操作系统分析实验四 设备驱动: Linux系统下的字符设备驱动程序编程

    Unix/Linux操作系统分析实验一 进程控制与进程互斥 Unix/Linux操作系统分析实验二 内存分配与回收:Linux系统下利用链表实现动态内存分配 Unix/Linux操作系统分析实验三 文 ...

  9. linux中split分割文件打开方式,Linux系统下使用split命令分割大文件 (转载)

    [小蜗牛闲情之作 ] 我想给一个朋友传一个大视频,有几百M,尝试多种传输办法失败后,最后想到的是把视频切开一片片"邮递"过去给他,让它自己组装起来吧. [root@pps publ ...

  10. linux第三方模块参数,nginx 的第三方模块ngx_http_accesskey_module 来实现下载文件的防盗链步骤(linux系统下)...

    nginx 的第三方模块ngx_http_accesskey_module 来实现下载文件的防盗链步骤(linux系统下),安装Nginx和HttpAccessKeyModule模块(参考LNMP环境 ...

最新文章

  1. 客户端爬取-答网友问
  2. JAVA_OPTS 参数
  3. Secure保存串口数据到本地
  4. 文巾解题 196. 删除重复的电子邮箱
  5. 中科院计算机全国重点实验室,国家重点实验室
  6. Mozilla “Common Voice” 开源语音识别项目
  7. 如何杀掉D状态的进程?[zt]【转】
  8. java ajax报错500,(Struts2+JSON+Ajax) XMLHttpRequest ==500如何解决
  9. linux ssh客户端_Linux终端连接Linux服务器
  10. ASP.NET把图片存入数据库和使用文件流读取显示(转)
  11. python实现json文件中向量写入Excel中
  12. 组策略设置计算机计划任务,组策略 运行计划任务 Powershell
  13. 软考高级信息系统项目管理师经验分享
  14. ctf比赛/学习资源整理,记得收藏!
  15. 关闭删库跑路的后门,打造高可用的MySQL
  16. random.uniform()和random.random()区别
  17. 【STL】string详解(string类常用的操作函数、构造函数、赋值操作、子符串的拼接、查找和替换、比较、存取、插入和删除、获取)
  18. 打卡系列-剑指 Offer 62. 圆圈中最后剩下的数字
  19. 毕业三年,快速升职加薪,带领数十人的技术团队,我是怎么做到的?
  20. 虚函数和纯虚函数的使用

热门文章

  1. php 上传微信客服头像,微信多客服上传头像
  2. 计算机专业就业崩溃,计算机专业就业“遇冷说”引发争议
  3. Java继承的特征和优势
  4. Python学习教程-1_Introductions
  5. 视差贴图(Parallax Mapping)
  6. 武汉理工大学计算机学院导师联系方式,武汉理工大学计算机学院导师一览表
  7. 短视频合集怎么做,教你快速合并的技巧
  8. ibm服务器维修检测报告,启创云小机(IBM POWER7)测试报告
  9. CorelDRAW VBA - 发布(导出)PDF文档
  10. 举个栗子~Minitab 技巧(6):使用 T 检验 分析产品质量