Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# 注意一定要在书写命令时,必须在命令开头敲一个Tab键,而不能使用4个空格(space)来代替Tab
# 这个模板,以后只需要更改文件名和链接文件夹即可!!!
# 惨痛教训,链接的时候要加上库:@g++ $(OBJS_C) $(OBJS_CPP) -o $(TARGET) -lcurl

# 根路径
ROOT := $(shell pwd)

# --------------------------修改区----------------------
# 添加链接编译文件的文件夹,有.cpp文件
SUBDIR := $(ROOT)
SUBDIR += $(ROOT)/func
SUBDIR += $(ROOT)/data

# 生成可执行程序的文件名
TARGET := main
# TARGET := test1

# 保存生成文件的文件夹
OUTPUT := ./output

# JSON 头文件路径
JSON_INCLUDE := /home/lb/mylib/json-develop/include/ # 将路径替换为你的 json.hpp 所在位置

# -----------------------------------------------------

# 编译文件夹
INCS := $(foreach dir,$(SUBDIR),-I$(dir))
INCS += -I$(JSON_INCLUDE) # 添加 JSON 头文件路径

# 筛选出c文件名,链接需要
SRCS_C := $(foreach dir,$(SUBDIR),$(wildcard $(dir)/*.c))
SRCS_CPP := $(foreach dir,$(SUBDIR),$(wildcard $(dir)/*.cpp))
# 筛选出c++文件名,链接需要
OBJS_C := $(patsubst $(ROOT)/%.c,$(OUTPUT)/%.o,$(SRCS_C))
OBJS_CPP := $(patsubst $(ROOT)/%.cpp,$(OUTPUT)/%.o,$(SRCS_CPP))


# g++ 提供了强大的自动生成依赖,记录有依赖关系的 *.d 文件————不用手动为每个源文件添加头文件依赖
DEPS := $(patsubst %.o,%.d,$(OBJS_C))
DEPS += $(patsubst %.o,%.d,$(OBJS_CPP))

# 开始链接
main : $(OBJS_C) $(OBJS_CPP)
@echo linking...
@g++ $(OBJS_C) $(OBJS_CPP) -o $(TARGET) -lcurl -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_legacy
@echo complete!

# c编译
$(OUTPUT)/%.o : %.c
@echo C compile $<...
@mkdir -p $(dir $@)
@gcc -MMD -MP -c $(INCS) $< -o $@ -lsocket -lnetwork -lcurl

# C++编译
$(OUTPUT)/%.o : %.cpp
@echo C++ compile $<...
@mkdir -p $(dir $@)
@g++ -std=c++11 -MMD -MP -c $(INCS) $< -o $@ -lsocket -lnetwork -lcurl -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_legacy

# 删除过程文件
.PHONY : clean

clean:
@echo try to clean...
@rm -r $(OUTPUT)
@echo complete!

-include $(DEPS)
168 changes: 168 additions & 0 deletions func/UpDownFile.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#include "../include/myhead.h"

/**
* 上传文件 服务器
* //开始写入 服务器检测STF标志位
* //结束写入 服务器检测EOF标志位
* 直接写入
*
*
* 解决粘包
* 粘包
* 发生端发送2个小数据包,接收端会一次性接收到这两个字符串,并将它们合并成一个较大的数据包
* 解决方法
* 消息前缀是一个4字节的整数,用于表示消息的长度
* 每次取数据步骤
* 1.先取4字节的消息前缀
* 2.按照消息前缀去取数据,根据长度来准确切割消息
*
*/
int UpLoadFile(int clientSocket, char *strFileName)
{
printf("客户端%d 上传任务\n", clientSocket);
// 参数判断
if (clientSocket < 0 || NULL == strFileName || strlen(strFileName) <= 0)
{
return -1;
}

// 从传输开始标志位STF起写入文件
// 连接-绝对路径
char str_file[512];
const char *base_path = DATA_PATH;
strcpy(str_file, base_path);
strcat(str_file, strFileName);
printf("客户端%d 服务器保存位置:%s\n", clientSocket, str_file);

// 打开本地文件以保存下载内容
FILE *file = fopen(str_file, "wb");
if (!file)
{
printf("客户端%d ", clientSocket);
perror("打开本地文件失败");
return -1;
}

// recv and fwrite
int iRet = -1;
char *buf = new char[BUF_SIZE_VIDEO]();
memset(buf, 0, BUF_SIZE_VIDEO);
while ((iRet = recv(clientSocket, buf, BUF_SIZE_VIDEO, 0)) > 0)
{
fwrite(buf, 1, iRet, file);
memset(buf, 0, iRet);
}


// 检测
if (iRet==0)
{
printf("客户端%d 文件上传成功\n", clientSocket);
}
else
{
printf("客户端%d 接收数据失败\n",clientSocket);
fclose(file);
delete[] buf;
return -1;
}

// 关闭资源
fclose(file);
delete[] buf;
return 0;
}

/**
* 下载文件 服务器
* 开始传输 服务器发送STF标志位
* 结束传输 服务器发送EOF标志位
*/
int DownLoadFile(int clientSocket, char *strFileName)
{
const char *stfFlag = "STF"; // 定义文件开始传输标志位
const char *eofFlag = "EOF"; // 定义文件结束传输标志位

printf("客户端%d 下载任务\n", clientSocket);
if (clientSocket < 0 || NULL == strFileName || strlen(strFileName) <= 0)
{
perror("非法参数\n");
return -1;
}
// send file size to client

// 查找并删除末尾的换行符--客户端处理
size_t len = strlen(strFileName);
if (len > 0 && strFileName[len - 1] == '\n')
{
strFileName[len - 1] = '\0'; // 将换行符替换为字符串终止符
}

// 绝对路径
char str_file[512];
const char *base_path = DATA_PATH;
strcpy(str_file, base_path);
strcat(str_file, strFileName);

struct stat stBuf;
memset(&stBuf, 0, sizeof(struct stat));
if (-1 == stat(str_file, &stBuf))
{
perror("错误");
printf("客户端%d 数据检测失败:%s\n", clientSocket, str_file);
return -1;
}

char *buf = new char[BUF_SIZE_VIDEO]();
memset(buf, 0, BUF_SIZE_VIDEO);

// 发送一个传输开始标志位STF
if (send(clientSocket, stfFlag, strlen(stfFlag), 0) == -1)
{
perror("发送 STF 标志位失败");
// 处理发送失败的情况——断开连接
delete[] buf;
return -1;
}
printf("客户端%d 发送传输标志位 %s\n", clientSocket, stfFlag);

// 打开文件
FILE *file = fopen(str_file, "rb");
if (!file)
{
printf("客户端%d 打开 %s 文件失败\n", clientSocket, str_file);
fclose(file);
delete[] buf;
return -1;
}
// read and send
int iRet = -1;
printf("客户端%d 开始发送...\n", clientSocket);

while ((iRet = fread(buf, 1, BUF_SIZE_VIDEO, file)) > 0)
{
// send
if (-1 == send(clientSocket, buf, iRet, 0))
{
perror("Error sending data");
break;
}
// printf("客户端%d:发送数据 %s\n", clientSocket, buf);
memset(buf, 0, BUF_SIZE_VIDEO);
}
printf("客户端%d 发送成功\n", clientSocket);

// 发送一个传输结束标志位EOF
if (send(clientSocket, eofFlag, strlen(eofFlag), 0) == -1)
{
perror("发送 EOF 标志位失败");
// 处理发送失败的情况——断开连接
fclose(file);
delete[] buf;
return -1;
}

fclose(file);
delete[] buf;
return 0;
}
Loading