私人云盘(自动云同步)

一、项目简介

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

相关推荐
..过云雨14 分钟前
网络计算器实现 - 自定义套接字+序列化+守护进程
网络·网络协议·tcp/ip
hugerat1 小时前
在AI的帮助下,用C++构造微型http server
linux·c++·人工智能·http·嵌入式·嵌入式linux
小宇的天下2 小时前
HBM(高带宽内存)深度解析:先进封装视角的技术指南
网络·人工智能
ha20428941942 小时前
Linux操作系统学习记录之----自定义协议(网络计算器)
linux·网络·学习
想唱rap2 小时前
MYSQL在ubuntu下的安装
linux·数据库·mysql·ubuntu
糖~醋排骨2 小时前
DHCP服务的搭建
linux·服务器·网络
huohaiyu2 小时前
网络中的一些基本概念
运维·服务器·网络
llddycidy2 小时前
峰值需求预测中的机器学习:基础、趋势和见解(最新文献)
网络·人工智能·深度学习
小林一直冲2 小时前
华为设备配置与命令
网络
dust_and_stars2 小时前
ubuntu24使用apt安装VS-code-server code-server
linux·服务器·windows