当前位置: 首页 > news >正文

项目_Linux_网络编程_私人云盘

概述

项目功能总述:

该项目使用TCP进行通信,实现文件的上传和下载。云盘的文件同步有手动同步、实时同步、定时同步这三种。本项目主要实现的是手动同步的功能,重点训练在如何使用TCP进行文件传输。

选择TCP的原因:

文件的传输需要可靠,因此选择TCP传输。

项目中需要解决的问题:

  • 文件如何上传和下载
  • 文件大小不确定如何处理
  • 文件个数不确定如何处理
  • 如何获取文件事件来实现实时同步
  • 如何使用定时器和守护进程来实现定时同步

传输文件时要解决的关键问题:

  • 如何处理文件路径,从而使得创建新文件的路径名正确
  • 如何处理TCP连包问题,封包拆包的自定义协议如何设定

编写Makefile

makefile编写整体思路:

该makefile的编写参考博文"8.Linux_Makefile" - "8、makefile编写技巧" - "8.3 分文件处理"。博文连接如下:8.Linux_Makefile-CSDN博客

文件创建: 

创建一个文件夹linux_test,在该文件夹下创建 "src、inc、obj目录"、"makefile文件"、"test.c文件"

在src文件中也创建一个 "makefile文件"

主目录下的makefile代码如下:

SRCDIR = $(shell pwd)/src
INCDIR = $(shell pwd)/inc
OBJDIR = $(shell pwd)/obj
SRC = $(wildcard $(SRCDIR)/*.c)
OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SRC)))
MAIN_SRCDIR = $(shell pwd)
SERVER_SRC = $(wildcard $(MAIN_SRCDIR)/server.c)
CLIENT_SRC = $(wildcard $(MAIN_SRCDIR)/client.c)
SERVER_OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SERVER_SRC)))
CLIENT_OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(CLIENT_SRC)))
CC = gcc
CFLAGS = -c -g -Wall -I $(INCDIR)
export OBJ OBJDIR CC CFLAGS all:debug $(SRCDIR) $(SERVER_OBJ) $(CLIENT_OBJ) server client
debug:
#	@echo "OBJDIR = $(OBJDIR)"
#	@echo "TEST_OBJ = $(TEST_OBJ)"
#调用其他makefile进行编译、汇编
$(SRCDIR):echo@make -C $@
echo:@echo "make start"
#编译、汇编server.c client.c 文件
$(SERVER_OBJ):server.c@$(CC) $(CFLAGS) $^ -o $@
$(CLIENT_OBJ):client.c@$(CC) $(CFLAGS) $^ -o $@
#链接全部.o生成可执行文件server client
server:$(OBJ) $(SERVER_OBJ)@$(CC) $^ -o server 
client:$(OBJ) $(CLIENT_OBJ)@$(CC) $^ -o client.PHONY:clean
clean:rm ./obj/*

src目录下的makefile代码如下:

all:debug $(OBJ)
debug:
#	@echo "OBJ = $(OBJ)"
#	@echo "OBJDIR = $(OBJDIR)"
$(OBJDIR)/%.o:%.c@$(CC) $(CFLAGS) $^ -o $@

TCP通信功能实现 

下面内容是以多进程并发形式编写服务端与客户端的代码,主要目的是实现通信的框架,使得双方可以进行通信。

 概述:

网络相关的代码封装在my_net.c、my_net.h中。

基本功能就是实现服务器与客户端可以相互通信。这里先使用单线程的方式进行框架的搭建。

具体实现逻辑见博文"13.1 Linux_网络编程_TCP/UDP" - "TCP" - "并发" - "多进程" 博文连接如下:

13.1 Linux_网络编程_TCP/UDP-CSDN博客

基本功能的my_net.h函数总览:

#ifndef __MY_NET_H
#define __MY_NET_H#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>#define BACKLOG 5 	//最大接入客户端数量//TCP Server
int Socket_TcpServerInit(int argc,char** argv);
int Socket_TcpServerAccept(int fd);
//TCP Client
int Socket_TcpClientInit(int argc,char** argv);
//通用
ssize_t Socket_Read(int fd, void *buf, size_t count);
ssize_t Socket_Write(int fd, void *buf, size_t count);
//多进程并发
void Set_SIGCHLD(void);
void SIGCHLD_Handler(int sig);#endif

1、服务端

1、初始化socket服务器

该函数实现了创建IPv4的TCPsocket、地址快速复用、绑定端口号、监听客户端的功能。

/** socket_init: 初始化socket服务器* @param argc: main中的argc* @param argv: main中的argv* @ret 创建的socket文件描述符,如果失败会自动退出进程,该值不需要判断有效性* */
int Socket_TcpServerInit(int argc,char** argv){int fd;struct sockaddr_in addr;//参数有效性判断if(argc != 3){printf("param err\n");printf("%s<ip><port>\n",argv[0]);exit(-1);}printf("server ip = %s\n",argv[1]);printf("server port = %s\n",argv[2]);//1.创建socketif((fd=socket(AF_INET,SOCK_STREAM,0))<0){//IPv4,TCP协议perror("socket");exit(-1);}//地址快速重用int flag=1,len=sizeof(int);if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&flag,len) == -1){perror("setsockopt");exit(-1);}//2.绑定IP、端口号addr.sin_family = AF_INET;    				  //IPv4addr.sin_port = htons(atoi(argv[2])); 		  //端口号,要转化为大端子节序addr.sin_addr.s_addr = inet_addr(argv[1]);    //IP地址:0表示在本网络上的本主机,即:自己if(bind(fd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in)) == -1){perror("bind");exit(-1);}//3.监听socketif(listen(fd,BACKLOG) == -1){ 	//允许最多接入5个客户端perror("listen");exit(-1);}return fd;
}

 2、优化的accept函数

这个函数主要功能还是accept,但是封装了一些错误处理和接入客户端信息打印的操作。

/** Socket_TcpServerAccept: 优化的accept函数* @param fd: 服务器的socket文件描述符* @ret: 接入的客户端的socket文件描述符,如果失败会自动退出进程,该值不需要判断有效性* */
int Socket_TcpServerAccept(int fd){int newfd;struct sockaddr_in newAddr;socklen_t newAddrlen;do{//printf("Debug:again accept\n");newfd = accept(fd,(struct sockaddr*)&newAddr,&newAddrlen);}while(newfd < 0 && errno == EINTR);//如果是信号中断导致的错误,则重新执行acceptif(newfd < 0){perror("accept");exit(-1);}else{printf("[%s,%d]connect,fd=%d\n",inet_ntoa(newAddr.sin_addr),ntohs(newAddr.sin_port),newfd);}return newfd;
}

2、客户端

 1、初始化socket客户端

该函数实现了创建IPv4的TCPsocket、设置要连接服务器的信息、连接服务器的操作

/** Socket_TcpClientInit: 初始化socket客户端* @param argc: main中的argc* @param argv: main中的argv* @ret 创建的socket文件描述符,如果失败会自动退出进程,该值不需要判断有效性* */
int Socket_TcpClientInit(int argc,char** argv){int fd;struct sockaddr_in addr;//参数有效性判断if(argc != 3){printf("param err\n");printf("%s<ip><port>\n",argv[0]);exit(-1);}printf("connect server ip = %s\n",argv[1]);printf("connect server port = %s\n",argv[2]);//1.创建socketif((fd=socket(AF_INET,SOCK_STREAM,0))<0){//IPv4,TCP协议perror("socket");exit(-1);}//2.设置链接服务器的IP、端口号addr.sin_family = AF_INET;    				  //IPv4addr.sin_port = htons(atoi(argv[2])); 		  //端口号,要转化为大端子节序addr.sin_addr.s_addr = inet_addr(argv[1]);    //IP地址:0表示在本网络上的本主机,即:自己//3.链接服务器if(connect(fd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in)) == -1){perror("connect");exit(-1);}return fd;
}

3、通用读/写 

1、优化的read函数

该函数主要功能还是read,但封装了一些错误处理、读前清空缓冲区、自动回收退出的客户端资源的操作。

/** Socket_Read: 优化的read函数* @param: 参数含义与read一样* @ret: 返回值含义与read一样,如果失败会自动退出进程,该值不需要判断有效性* */
ssize_t Socket_Read(int fd, void *buf, size_t count){ssize_t	read_num;//读取数据do{//printf("Debug:again read\n");//清空缓冲区memset(buf,0,count);read_num = read(fd,buf,count);}while(read_num < 0 && errno == EINTR);//如果是信号中断导致的错误,则重新执行readif(read_num < 0){perror("read");exit(-1);}else if(read_num == 0){printf("Debug:read_num = 0,close fd=%d\n",fd);close(fd);}return read_num;
}

2、 优化的write函数

该函数主要功能还是write,但封装了一些错误处理、自动回收退出的客户端资源的操作。

/** Socket_Write: 优化的write函数* @param: 参数含义与write一样* @ret: 返回值含义与write一样,如果失败会自动退出进程,该值不需要判断有效性* */
ssize_t So

http://www.mrgr.cn/news/63748.html

相关文章:

  • 推荐一款用来快速开发3D建筑模型软件:Allplan
  • [Python基础](5) Python列表( list )详细解读
  • std::optional与函数返回值的讨论
  • Python:入门基础
  • day 5
  • [Python学习日记-59] 开发基础练习2——网站访问日志分析
  • Linux用户权限管理
  • Linux操作系统下载(centos)
  • 操作系统-多线程案例
  • 5天学习RAG路线图,你信吗?
  • 遥感图像Trento原始数据集下载
  • 如何在 Vue 页面中禁止选择、右键、复制及 F12 开发者工具
  • shell脚本编程
  • 奥数与C++小学四年级(第十八题 小球重量)
  • excel的宏1
  • 2024 年河南省高等职业教育技能大赛实施方案概述
  • 智能指针(内存泄漏问题)
  • JavaScript网页设计案例:智慧社区可视化大屏的实现
  • 如何使用和打开jconsole
  • 基于Python的黑龙江旅游景点数据分析系统【附源码】
  • Qml-Gif的显示
  • C语言结构体 变量对齐原理
  • MySQL-如果你在添加外键时忘加约束名,如何找到系统默认的约束名
  • vue2开发 对接后端(go语言)常抛异常情况以及处理方法汇总
  • 智能合约中的AI应用
  • 构造小练习