目录
1云盘项目简介
2 项目实现
2.1 首先实现TCP客户端、服务端
2.2 实现客户端函数简化
2.3 实现服务端函数简化
2.4 TCP数据连包现象
2.5 封装send函数和recv函数
2.6 建立readme说明
2.7 实现文件传输
2.8 读取配置文件种的ip、端口号,通过argv[1]参数实现文件传输
3 最终项目
常见的云盘服务软件
什么是云同步?
需求分析
如何实现手动同步?
cloud-project_v1
为了方便管理头文件,新建tcp.h
#ifndef _TCP_H
#define _TPC_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ErrExit(msg) do{ perror(msg); \ //异常处理宏定义
exit(EXIT_FAILURE);\
}while(0);
typedef struct sockaddr Addr;
typedef struct sockaddr_in Addr_in;
#define BACKLOG 5
#endif
实现server.c
#include "tcp.h"
int main(int argc, char *argv[])
{
int ret, fd, newfd;
Addr_in addr,client_addr;
socklen_t addrlen = sizeof(client_addr);
char buf[BUFSIZ] = {};
//检查参数
if(argc < 3)
{
fprintf(stderr, "%s \n", argv[0]);
exit(EXIT_FAILURE);
}
//创建套接字
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
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(bind(fd,(Addr *)&addr, sizeof(addr)))
ErrExit("bind");
//监听模式
if(listen(fd, BACKLOG))
ErrExit("listen");
//接收客户端链接
bzero(&client_addr,sizeof(client_addr));
do
{
newfd = accept(fd, (Addr *)&client_addr, &addrlen);
}while(newfd < 0 && errno == EINTR);
if(newfd < 0)
ErrExit("accept");
//接收客户端数据
while(1)
{
do
{
ret = recv(newfd, buf, BUFSIZ, 0);
}while(ret < 0 && errno == EINTR); //如果信号导致的错误,继续执行
if(ret < 0)
{
ErrExit("recv");
}
else if(!ret) //ret = 0 客户端退出
{
break;
}
else //ret > 0
{
printf("[%s:%d]buf:%s\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port), buf);
}
}
close(newfd);
close(fd);
return 0;
}
实现服务端client.c(复制服务端进行改动)
#include "tcp.h"
int main(int argc, char *argv[])
{
int ret, fd;
Addr_in addr;
char buf[BUFSIZ] = {"===test"};
//检查参数
if(argc < 3)
{
fprintf(stderr, "%s \n", argv[0]);
exit(EXIT_FAILURE);
}
//创建套接字
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
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(fd,(Addr *)&addr, sizeof(addr)))
ErrExit("bind");
//发送数据
while(1)
{
do
{
ret = send(fd, buf, BUFSIZ, 0);
}while(ret < 0 && errno == EINTR); //如果信号导致的错误,继续执行
if(ret < 0)
{
ErrExit("recv");
}
else if(!ret) //ret = 0
{
break;
}
printf("send data:%s\n", buf);
fflush(stdout);
getchar();
}
close(fd);
return 0;
}
最终实现效果,客户端发送,服务端打印===test
cloud_project_v1.1客户端给服务端传文件
主要工作:
tcp.h
#ifndef _TCP_H_
#define _TCP_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BACKLOG 5
#define ErrExit(msg) do { perror(msg); \
exit(EXIT_FAILURE); } while(0)
typedef struct sockaddr Addr;
typedef struct sockaddr_in Addr_in;
void Argment(int argc, char *argv[]);
int SocketInit(char *argv[]);
#endif
tcp.c
#include "tcp.h"
void Argment(int argc, char *argv[]){
if(argc < 3){
fprintf(stderr, "%s \n", argv[0]);
exit(EXIT_FAILURE);
}
}
int SocketInit(char *argv[]){
int fd;
Addr_in addr;
/*创建套接字*/
if( (fd = socket(AF_INET, SOCK_STREAM, 0) ) < 0)
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(fd, (Addr *)&addr, sizeof(addr) ) )
ErrExit("connect");
return fd;
}
client.c
#include "tcp.h"
int main(int argc, char *argv[])
{
int fd;
int ret;
char buf[BUFSIZ] = {"===test==="};
/*检查参数*/
Argment(argc, argv);
fd = SocketInit(argv);
/*发送数据*/
while(1){
do {
ret = send(fd, buf, BUFSIZ, 0);
}while(ret < 0 && errno == EINTR); //如果信号导致的错误,继续执行
if(ret < 0)
ErrExit("recv");
else if(!ret)
break;
printf("send data:%s", buf);
fflush(stdout);
getchar();
}
close(fd);
return 0;
}
server.c
#include "tcp.h"
int main(int argc, char *argv[])
{
int ret, fd, newfd;
Addr_in addr,client_addr;
socklen_t addrlen = sizeof(client_addr);
char buf[BUFSIZ] = {};
//检查参数
if(argc < 3)
{
fprintf(stderr, "%s \n", argv[0]);
exit(EXIT_FAILURE);
}
//创建套接字
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
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);
}
//绑定通