私人云盘(自动云同步)

一、项目简介

        模仿小米的云服务,实现一个通过TCP实现的私人云盘,因为能力有限,所以只实现自动云同步这一个功能,具体可以分为三个小功能,即保持云端和终端数据一致、实现文件的上传与下载以及手动同步

二、涉及到的知识点

        主要有文件的打开与关闭,文件的发送与接收,文件的写入及socket通信,为了项目整体的间接性,还使用到的枚举类型的结构体以及链表

三、TCP通信实现流程图

四、讲解

在项目实现过程中,代码程序修改了多次,我将最终的项目程序压缩包上传到了我的资源上面,有兴趣的可以自行下载。

这里放的程序是我在编写项目程序过程中的一个版本,只实现了单个文件的传输,需要自己手动输入要传输的文件,最终的版本在资源里面请不要搞错了

1、文件说明:

        ①client.c       是客户端的代码

        ②server.c      是服务器端的代码

        ③tcp.c          是客户端和服务器所使用到的一些头文件,以及自己封装的一些函数和自定义的宏

        ④Makefile     这个就不用多说了吧

2、程序文件

client.c文件

#include "tcp.h"
#define FILENAME "森林风声-呜呼呜呼-树木摇曳.mp3"

int main(int argc,char *argv[]){
    int socketfd,filefd;
    int ret;
    char buf[BUFSIZ];
    /*检查参数*/
    Argment(argc,argv);
    /*创建套接字并对其初始化*/
    socketfd = SocketInit_Client(argv);
    /*打开文件*/
    filefd = open(FILENAME,O_RDONLY);
    if(filefd == -1){
        ErrExit("open");
    }
    /*发送文件名字*/
    SocketDataHandle(socketfd,FILENAME,strlen(FILENAME),(DataHand_t)send);
    SocketDataHandle(socketfd,buf,1,recv);
    /*发送文件内容*/
    if(buf[0] == OK){
        while(1){
            do{
                ret = read(filefd,buf,BUFSIZ);
            }while(ret < 0 && errno == EINTR);
        if(ret < 0){
            ErrExit("read");
        }
        if(!ret){
            break;
        }
        ret = SocketDataHandle(socketfd,buf,ret,(DataHand_t)send);
        if(!ret){
            break;
        }
        }
    }
    close(filefd);
    close(socketfd);
    return 0;
}


server.c文件

#include "tcp.h"

int main(int argc,char *argv[]){
    int socketfd,newsocketfd,filefd;
    int ret;
    char buf[BUFSIZ] = {};
    Addr_in clientaddr;
    socklen_t addrlen = sizeof(Addr_in);
    /*检查参数*/
    Argment(argc,argv);
    /*创建套接字*/
    socketfd = SocketInit_server(argv);
    /*接收客户端的连接并生成一个新的套接字*/
    do{
        newsocketfd = accept(socketfd,(Addr *)&clientaddr,&addrlen);
     }while(newsocketfd < 0 && errno == EINTR);  //erron=EINTR如果信号导致的中断,重新执行一次
    if(newsocketfd == -1){
        ErrExit("accept");
    }
    /*接收文件名字*/
    ret = SocketDataHandle(newsocketfd,buf,BUFSIZ,recv);
    /*创建文件*/
    filefd = open(buf,O_WRONLY|O_CREAT,0660);
    if(filefd == -1){
        ErrExit("open");
    }
    buf[0] = OK;
    SocketDataHandle(newsocketfd,buf,1,(DataHand_t)send);
    /*接收文件*/
    while(1){
        ret = SocketDataHandle(newsocketfd,buf,BUFSIZ,recv);
        if(!ret){
            break;
        }
        write(filefd,buf,ret);
    }
    close(filefd);
    close(newsocketfd);
    close(socketfd);
    return 0;
}
 

tcp.h文件

#ifndef _TCP_H_
#define _TCP_H_

/*使用的头文件*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <math.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

/*自己定义的宏*/
#define ErrExit(msg) do{perror(msg); exit(EXIT_FAILURE);}while(0)
#define BACKLOG 5
#define OK '1'
typedef struct sockaddr Addr;
typedef struct sockaddr_in Addr_in;
typedef ssize_t(* DataHand_t)(int ,void *,size_t,int);

/*函数声明*/
void Argment(int argc,char *argv[]);
int SocketInit_Client(char *argv[]);
int SocketInit_server(char *argv[]);
int SocketDataHandle(int fd,void *buf,size_t len,DataHand_t datahandle);

//参数检查函数
void Argment(int argc,char *argv[]){
    if(argc < 3){
        fprintf(stdin,"%s<addr><port>\n",argv[0]);
        exit(EXIT_FAILURE);
    }
}

//初始化客户端套接字函数
int SocketInit_Client(char *argv[]){
    int socketfd;
    Addr_in addr;
    /*创建套接字*/
    socketfd = socket(AF_INET,SOCK_STREAM,0);
    if(socketfd == -1){
        ErrExit("socket");
    }
    /*设置通信结构体*/
    bzero(&addr,sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(argv[2]));
    if(inet_aton(argv[1],&addr.sin_addr) == 0){
        fprintf(stderr,"Invalid address\n");
        exit(EXIT_FAILURE);
    }
    /*发起连接请求*/
    if(connect(socketfd,(Addr *)&addr,sizeof(addr)) == -1){
        ErrExit("connect");
    }
    return socketfd;
}

//初始化服务器端套接字函数
int SocketInit_server(char *argv[]){
    int socketfd;
    Addr_in addr;
    /*创建套接字*/
    socketfd = socket(AF_INET,SOCK_STREAM,0);
    if(socketfd == -1){
        ErrExit("socket");
    }
    /*设置地址快速重用*/
    int flag = 1;
    if(setsockopt(socketfd,SOL_SOCKET,SO_REUSEADDR,&flag,sizeof(flag)) == -1){
        perror("setsockopt");
    }
    /*设置通信结构体*/
    bzero(&addr,sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(argv[2]));
    if(inet_aton(argv[1],&(addr.sin_addr)) == 0){
        fprintf(stderr,"Invalid address\n");
        exit(EXIT_FAILURE);
    }
    /*绑定通信结构体*/
    if(bind(socketfd,(Addr *)&addr,sizeof(addr)) == -1){
        ErrExit("bind");
    }
    /*设置套接字的模式为监听*/
    if(listen(socketfd,BACKLOG) == -1){
        ErrExit("listen");
    }
    return socketfd;
}

//数据处理函数
int SocketDataHandle(int fd,void *buf,size_t len,DataHand_t datahandle){
    int ret;
    char *str = datahandle == recv?"recv":"send";
    do{
        ret = datahandle(fd,buf,len,0);
    }while(ret < 0 && errno == EINTR);
    if(ret < 0){
        ErrExit(str);
    }
    return ret;
}

#endif

Makefile文件


all:server client
CC=gcc
CFLAGS=-g -Wall

server:server.c
client:client.c

MV_client:
    mv client /mnt/hgfs/Share/

clean:server client
    rm server client

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/701580.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【每日刷题】Day62

【每日刷题】Day62 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 852. 山脉数组的峰顶索引 - 力扣&#xff08;LeetCode&#xff09; 2. 2806. 取整购买后的账户余额…

WWDC 2024及其AI功能的引入对中国用户和开发者的影响

WWDC&#xff08;Apple Worldwide Developers Conference&#xff09;是苹果公司一年一度的重要活动&#xff0c;吸引了全球开发者的关注。WWDC 2024引入了许多新技术和功能&#xff0c;尤其是AI功能的加入&#xff0c;引发了广泛讨论。本文将深入探讨中国开发者如何看待WWDC 2…

Prisma数据库ORM框架学习

初始化项目 中文网站 点击快速开始,点击创建sql项目,后面一步一步往后走 这个博主也挺全的,推荐下 可以看这个页面初始化项目跟我下面是一样的,这里用得是ts,我下面是js,不需要额外的配置了 1.vscode打开一个空文件夹 2.npm init -y 初始化package.json 3.安装相关依赖 …

JAVA中验证码工具类的封装

1. 方案一 Java内部方法生成&#xff0c;不需要其它依赖 样式如图所示&#xff1a; package com.hyh.ad.common.utils;import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.File;…

C语言 sizeof 和 strlen

目录 一、sizeof 和 strlen 的区别 a.sizeof b.strlen c.sizeof与strlen的区别 二、数组和指针笔试题解析(32位环境) a.一维数组( int a[ ] { 1 , 2 , 3 , 4 } ) b.字符数组 &#xff08;char arr[ ] {a , b , c , d , e , f }&#xff09; &#xff08; char arr[ …

Ubuntu系统调试分析工具

文章目录 一、火焰图一、下载 FlameGraph二、安装 iperf三、使用二、Lockdep1、内核开启 Lockdep 配置2、判断 Lockdep 开启是否成功一、火焰图 一、下载 FlameGraph git clone https://github.com/brendangregg/FlameGraph.gitFlameGraph 介绍:   基本思想是将程序的函数…

vue生成二维码中间自定义logo并截图分享

需求描述&#xff1a;在公众号中&#xff0c;生成二维码&#xff0c;并在二维码中央添加自定义logo&#xff0c;然后生成一张分享给好友的 二维码图片。 一、用到的依赖包 npm install --save html2canvas <script srchttps://cdn.staticfile.org/jquery/2.1.1/jquery.min…

nvm 安装说明

1、下线nvm地址 https://nvm.uihtm.com/2、安装步骤 2.1、双击解压后的exe 2.2、选择I accept…&#xff0c;然后点击next 2.3、选择nvm安装位置,选择好后点击next 2.4、选择nodejs的安装位置&#xff0c;点击next&#xff0c;记住你的nodejs路径&#xff01;甚至可以复制这…

[数据集][目标检测]叶子计数检测数据集VOC+YOLO格式240张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;240 标注数量(xml文件个数)&#xff1a;240 标注数量(txt文件个数)&#xff1a;240 标注类别…

C语言的数据结构:串、数组、广义表

一、串 1、串的定义 串是一个线性表&#xff0c;但其节点中的内容只能为字符&#xff0c;所以也称为字符串。 字符串中可以有多个字符&#xff0c;也可以没有字符。没有字符的叫作&#xff1a;空串。 空串&#xff1a;""。 有值的串&#xff1a;"1123"。 只…

Handler通信机制

目标&#xff1a; 1.Handler和Looper什么关系&#xff1f; 一个Looper对应一个MessageQueue&#xff0c;可以多个handler往MessageQueue发送消息。 2.一个线程有几个Handler&#xff1f; 3.Handler内存泄漏的原因&#xff1f; 4.使用Message时如何创建它&#xff1f; 5.子…

重生奇迹MU剑士介绍

剑士拥有过人的体力及华丽的剑术&#xff0c;加上属于近距离攻击型职业&#xff0c;就算没有其他角色的帮助也可自行锻炼。由于剑士是剑术的专家&#xff0c;所以无法学习魔法&#xff0c;但与其他角色组队冒险时&#xff0c;因优异的体力通常是担任先锋角色。剑士等级达到150级…

SSM 离散数学线上考试系统-计算机毕业设计源码83059

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;高校当然也不例外。离散数学线上考试系统是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;采…

VB.NET实现上位机自动识别可用串口

在实际应用中有时会牵扯到挑选可用串口&#xff0c;比如上位机和从站设备使用Modbus RTU协议进行通讯时需要选择COM串口&#xff0c;每次启动连接前都在设备管理器查看较为麻烦&#xff0c;可以设置一个串口自动识别功能&#xff0c;如果选择了错误的串口还可以提示串口选择错误…

借助Historian Connector + TDengine,打造工业创新底座

在工业自动化的领域中&#xff0c;数据的采集、存储和分析是实现高效决策和操作的基石。AVEVA Historian (原 Wonderware Historian) 作为领先的工业实时数据库&#xff0c;专注于收集和存储高保真度的历史工艺数据。与此同时&#xff0c;TDengine 作为一款专为时序数据打造的高…

排名前五的 Android 数据恢复软件

正在寻找数据恢复软件来从 Android 设备恢复数据&#xff1f;本指南将为您提供 5 款最佳 Android 数据恢复软件。浏览这些软件&#xff0c;然后选择您喜欢的一款来恢复 Android 数据。 ndroid 设备上的数据丢失可能是一种令人沮丧的经历&#xff0c;无论是由于意外删除、系统崩…

【Redis】Redis常见问题——缓存更新/内存淘汰机制/缓存一致性

目录 回顾数据库的问题如何提高 mysql 能承担的并发量&#xff1f;缓存解决方案应对的场景 缓存更新问题定期生成如何定期统计定期生成的优缺点 实时生成maxmemory 设置成多少合适呢&#xff1f;项目类型上来说 新的问题 内存淘汰策略Redis淘汰策略为什么redis要内存淘汰内存淘…

Echarts自定义地图显示区域,可以显示街道,小区,学校等区域

&#x1f680;&#x1f680;​​​​​​​&#x1f680;​​​​​​​目录 自定义地图 1. 选择边界生成器 2.导出JSON&#xff0c;在vue中使用&#xff1a; 3. vue中使用自定义地图 4.两个面、两条线&#xff0c;4个features&#xff0c;在每一个properties中添加name属…

英语四六级考试听力同频无线转发系统在上海电子信息职业技术学院的应用

英语四六级考试听力同频无线转发系统在上海电子信息职业技术学院的应用 由北京海特伟业科技有限公司任洪卓发布于2024年6月12日 一、 英语考试听力同频无线转发系统建设背景 英语听力考试作为评估大学生英语能力的重要一环&#xff0c;其顺利进行对于保障考试公平性和学生权益…

6月报名 | 海克斯康Actran风机类气动噪声分析培训

您好&#xff01;感谢您长期以来对优飞迪科技与海克斯康的关注与支持。我们诚邀您参加海克斯康Actran风机类气动噪声分析培训&#xff0c;特邀海克斯康原厂讲师将以实操为基础&#xff0c;结合真实案例&#xff0c;手把手帮您解锁噪声仿真关键技术。 活动主题&#xff1a; 海…