私人云盘(自动云同步)

一、项目简介

模仿小米的云服务,实现一个通过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

相关推荐
blessing。。11 分钟前
I2C学习
linux·单片机·嵌入式硬件·嵌入式
2202_7544215425 分钟前
生成MPSOC以及ZYNQ的启动文件BOOT.BIN的小软件
java·linux·开发语言
ZZZCY200338 分钟前
华为ENSP--IP编址及静态路由配置
网络·华为
EasyCVR1 小时前
私有化部署视频平台EasyCVR宇视设备视频平台如何构建视频联网平台及升级视频转码业务?
大数据·网络·音视频·h.265
运维&陈同学1 小时前
【zookeeper03】消息队列与微服务之zookeeper集群部署
linux·微服务·zookeeper·云原生·消息队列·云计算·java-zookeeper
hgdlip1 小时前
主IP地址与从IP地址:深入解析与应用探讨
网络·网络协议·tcp/ip
旦沐已成舟1 小时前
DevOps-Jenkins-新手入门级
服务器
珹洺2 小时前
C语言数据结构——详细讲解 双链表
c语言·开发语言·网络·数据结构·c++·算法·leetcode
科技象限2 小时前
电脑禁用U盘的四种简单方法(电脑怎么阻止u盘使用)
大数据·网络·电脑
东方隐侠安全团队-千里2 小时前
网安瞭望台第3期:俄黑客 TAG - 110组织与密码攻击手段分享
网络·chrome·web安全·网络安全