网络编程项目之FTP服务器
项目介绍
模拟FTP核心原理:客户端连接服务器后,向服务器发送一个文件。文件名可以通过参数指定,服务器端接收客户端传来的文件(文件名随意),如果文件不存在自动创建文件,如果文件存在,那么清空文件然后写入。
项目功能介绍:
均有服务器和客户端代码,基于TCP写的。
在同一路径下,将客户端可执行代码复制到其他的路径下,接下来在不同的路径下运行服务器和客户端。
相当于另外一台电脑在访问服务器。
客户端和服务器链接成功后出现以下提示:四个功能
***************list************** //列出服务器所在目录下的文件名(除目录不显示)
***********put filename********** //上传一个文件
***********get filename********** //从服务器所在路径下载文件
**************quit*************** //退出(可只退出客户端,服务器等待下一个客户端链接)
FTP客户端
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>char buf[128] = {};
//客户端函数声明
void putfileC(char *buf, int sockfd); //客户端上传文件到服务器功能函数
void getfileC(char *buf, int sockfd); //客户端从服务器下载文件功能函数
void list(int sockfd);int main(int argc, char const *argv[])
{// 1.创建套接字int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket err:");return -1;}// 2.填充结构体(ipv4)struct sockaddr_in addr;addr.sin_family = AF_INET; // 协议族ipv4addr.sin_port = htons(atoi(argv[2])); // 端口号(网络字节序)addr.sin_addr.s_addr = inet_addr(argv[1]); // ip地址(网络字节序)// 3.连接if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0){perror("connect err");return -1;}//4.发送while (1){fgets(buf, sizeof(buf), stdin);if (buf[strlen(buf) - 1] == '\n'){buf[strlen(buf) - 1] = '\0';}if (strcmp(buf, "quit") == 0){break;}if (strcmp(buf, "list") == 0){send(sockfd, buf, sizeof(buf), 0);list(sockfd);}if (strncmp(buf, "put ", 4) == 0){send(sockfd, buf, sizeof(buf), 0);putfileC(buf, sockfd);printf("put ok\n");}if (strncmp(buf, "get ", 4) == 0){send(sockfd, buf, sizeof(buf), 0);getfileC(buf, sockfd);printf("get ok\n");}}//5.关闭文件close(sockfd);return 0;
}void list(int sockfd)
{while (1){recv(sockfd, buf, sizeof(buf), 0);if (strcmp(buf, "end") == 0){break;}elseprintf("%s ", buf);}printf("\n");return;
}void putfileC(char *buf, int sockfd)
{int fd = open(buf + 4, O_RDONLY);if (fd < 0){perror("fd client err");return;}ssize_t ret;while (1){ret = read(fd, buf, sizeof(buf));if (ret == 0){break;}send(sockfd, buf, sizeof(buf), 0);memset(buf, 0, 128);}send(sockfd, "end", sizeof(buf), 0);close(fd);return;
}void getfileC(char *buf, int sockfd)
{int fd = open(buf + 4, O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd < 0){perror("fd err");return;}ssize_t ret;while (1){memset(buf, 0, 128);ret = read(sockfd, buf, sizeof(buf));if (strcmp(buf, "end") == 0){break;}write(fd, buf, strlen(buf));}close(fd);return;
}
FTP服务器
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>char buf[128] = {};
//服务器函数声明
void menu(); //显示目录
void list(int acceptfd); //列出服务器当前路径的文件名
void putfileS(char *buf, int acceptfd); //服务器接受客户端上传文件功能函数
void getfileS(char *buf, int acceptfd); //服务器下载文件到客户端功能函数int main(int argc, char const *argv[])
{//避免少输,出现段错误if (argc != 2){printf("please input %s ip port\n", argv[0]);return -1;}// 1.创建套接字int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket err:");return -1;}// 2.填充结构体(ipv4)struct sockaddr_in addr, caddr; //客户端连接的时候会自己填充信息,只需给它个空间addr.sin_family = AF_INET; // 协议族ipv4addr.sin_port = htons(atoi(argv[1])); // 端口号(网络字节序)addr.sin_addr.s_addr = INADDR_ANY; // ip地址(网络字节序)// addr.sin_addr.s_addr = inet_addr("0.0.0.0");// 3.绑定int ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));if (ret < 0){perror("bind err:");return -1;}// 4.监听if (listen(sockfd, 5) < 0){perror("listen err");return -1;}//5.循环等待连接socklen_t len = sizeof(caddr);while (1){//有客户端连接就显示目录// 5.等待连接int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);if (acceptfd < 0){perror("accpet err:");return -1;}printf("acceptfd = %d\n", acceptfd);printf("client: ip=%s port=%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));// 6.接收menu();while (1){ret = recv(acceptfd, buf, sizeof(buf), 0);if (ret == -1){perror("recv err:");return -1;}else if (ret == 0){printf("client exit\n");break;}else{if (strcmp(buf, "list") == 0){list(acceptfd);}if (strncmp(buf, "put ", 4) == 0){putfileS(buf, acceptfd);printf("put end\n");}if (strncmp(buf, "get ", 4) == 0){getfileS(buf, acceptfd);printf("get end\n");}}}// 7.关闭close(acceptfd);}close(sockfd);return 0;
}void menu() //显示目录
{printf("***************list**************\n");printf("***********put filename**********\n");printf("***********get filename**********\n");printf("**************quit***************\n");
}
//列出服务器所在目录下的文件名(除目录不显示)
void list(int acceptfd)
{DIR *dirp;struct dirent *d;dirp = opendir("./");if (NULL == dirp){perror("opendir err");return;}struct stat st;while ((d = readdir(dirp)) != NULL){if (stat(d->d_name, &st) < 0){perror("stat err");return;}if ((st.st_mode & S_IFMT) == S_IFREG){send(acceptfd, d->d_name, sizeof(d->d_name), 0);}}send(acceptfd, "end", sizeof(buf), 0);
}
//服务器接受客户端上传文件功能函数
void putfileS(char *buf, int acceptfd)
{int fd = open(buf + 4, O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd < 0){perror("fd server err");return;}ssize_t ret;while (1){memset(buf, 0, 128);ret = recv(acceptfd, buf, sizeof(buf), 0);if (strcmp(buf, "end") == 0){break;}write(fd, buf, strlen(buf));}close(fd);return;
}
//服务器下载文件到客户端功能函数
void getfileS(char *buf, int acceptfd)
{int fd = open(buf + 4, O_RDONLY);if (fd < 0){perror("fd err");return;}ssize_t ret;while (1){ret = read(fd, buf, sizeof(buf));if (ret == 0){break;}send(acceptfd, buf, sizeof(buf), 0);memset(buf, 0, 128);}send(acceptfd, "end", sizeof(buf),0);close(fd);return;
}
问题
函数参数时把数组名传进去了,导致计算数组长度时报错,原因就是数组名被当作函数参数时会被降级为指针。
编译器警告:sizeof on array function parameter “arr‘ will return size “用另一个值除指针的sizeof值”,sizeof(数组名)时会遇到的坑-CSDN博客
c++数组传递参数与返回_function cannot return function type-CSDN博客
函数使用数组的报错_sizeof' on array function parameter 'a' will retur-CSDN博客
粘包问题: 上传或下载都出现过服务器或客户端卡主现象,原因就是粘包问题没有解决,导致判断结束的"end"包与数据包粘在一起,判断条件不能满足跳不出循环一直卡主。目前我能解决的就是加个sleep函数先让发送或者接收数据的一方睡眠个几秒,或者收和发长度一致。
相关文章:
网络编程项目之FTP服务器
项目介绍 模拟FTP核心原理:客户端连接服务器后,向服务器发送一个文件。文件名可以通过参数指定,服务器端接收客户端传来的文件(文件名随意),如果文件不存在自动创建文件,如果文件存在࿰…...

SpringBoot02:第一个springboot程序
3、第一个springboot程序 3.1、准备工作 我们将学习如何快速的创建一个Spring Boot应用,并且实现一个简单的Http请求处理。通过这个例子对Spring Boot有一个初步的了解,并体验其结构简单、开发快速的特性。 我的环境准备: java version "…...

快速入门HTML
欢迎关注个人主页:逸狼 创造不易,可以点点赞吗 如有错误,欢迎指出~ 目录 第一个html文件 标签 h1~h6 p >段落标签 br > 换行标签 img >图片标签 a >超链接标签 表格标签 表单标签 表单控件 form表单 ⽆语义标签:div&span 综…...

RabbitMQ是一个开源的消息代理和队列服务器
RabbitMQ是一个开源的消息代理和队列服务器,它基于AMQP(Advanced Message Queuing Protocol,高级消息队列协议)协议实现,同时也支持其他消息协议如STOMP、MQTT等。作为一个可靠的消息传递服务,RabbitMQ在分…...
经典算法思想--并查集
前言 (最近在学习Java,所有函数都是用Java语言来书写的)前言部分是一些前提储备知识 在并查集(Union-Find)数据结构中,rank(中文称为“秩”)是用来表示树的高度或深度的一种辅助信息…...
挑战Java面试题复习第2天,百折不挠
挑战第 2 天 ArrayList和linkedList的区别HashMap和HashTable的区别Collection 与 Collections 的区别Java的四种引用泛型常用特点 ArrayList和linkedList的区别 底层数据结构: ArrayList:基于动态数组实现,支持快速随机访问。LinkedList&a…...

【vue之道】
vue之道 1. 一生二,二生万物思想2. 变化之律3. 变化之实在哪?4.而后学于形乃已!4.1 展示之形变4.2 动之气谓之指令4.3 血之养分的载体,于vue之绑定载具4.4 vue之道(万法规一篇) 1. 一生二,二生万…...

基于麻雀优化算法SSA的CEEMDAN-BiLSTM-Attention的预测模型
往期精彩内容: 时序预测:LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较 全是干货 | 数据集、学习资料、建模资源分享! EMD、EEMD、FEEMD、CEEMD、CEEMDAN的区别、原理和Python实现(一)EMD-CSDN博客 EMD、EEM…...

Linux:指令再认识
文章目录 前言一、知识点1. Linux下一切皆文件,也就是说显示器也是一种文件2. 指令是什么?3. ll 与 ls -l4. 日志5. 管道6. 时间戳 二、基本指令1. man指令2. cp指令3. mv指令4. 查看文件1)cat/tac指令——看小文件2)more/less指令…...
PHP如何抛出和接收错误
在PHP中,抛出和接收错误通常涉及异常处理机制,以及错误和异常的处理函数。以下是如何在PHP中抛出和接收错误的详细指南: 抛出错误(异常) 在PHP中,你可以使用throw关键字来抛出一个异常。这通常在你检测到…...

计算机网络:网络层 —— IPv4 地址的应用规划
文章目录 IPv4地址的应用规划定长的子网掩码变长的子网掩码 IPv4地址的应用规划 IPv4地址的应用规划是指将给定的 IPv4地址块 (或分类网络)划分成若干个更小的地址块(或子网),并将这些地址块(或子网)分配给互联网中的不同网络,进而可以给各网络中的主机…...
Mongodb命令大全
Mongodb命令大全 一、数据库相关命令二、集合相关命令三、文档(数据)相关命令1、_id 字段说明2、查询2.1、 查询操作符2.2、内嵌文档查询2.3、数组文档查询2.4、去重查询2.5、查询排序 sort2.6、分页查询2.7、指定列投影查询返回2.8、查询统计个数 count 3、聚合查询3.1、查询用…...

宇视设备视频平台EasyCVR视频融合平台果园/鱼塘/养殖场/菜园有电没网视频监控方案
在那些有电无网的偏远地区,如果园、鱼塘、养殖场或菜园,视频监控的实现面临着独特的挑战。宇视设备视频平台EasyCVR提供了一种创新的解决方案,通过结合太阳能供电和4G摄像头技术,有效地解决了这些场景下的监控需求。 在有电没网的…...
面试题:ABCD四个线程,A线程最后执行
我觉得是一个很高频的面试题,ABCD四个线程,A线程要等到BCD线程执行完再执行,怎么做 因为我刚复习完AQS,所以立马想到了CountDownLatch,但是看面试官反应他最想听到的应该是join方法,所以面试后就总结了几种…...

代码随想录算法训练营第46期Day43
leetcode.322零钱兑换 class Solution { public: //无限个硬币->完全背包int coinChange(vector<int>& coins, int amount) {vector<int> dp(10010,INT_MAX);//dp代表的在某个数值下最小的硬币数,要求是最小的硬币数,所以初始值要尽可…...
前端处理API接口故障:多接口自动切换的实现方案
因为在开发APP,一个接口如果不通(被挂了)又不能改了重新打包让用户再下载软件更新,所以避免这种情况,跟后端讨论多备用接口地址自动切换的方案,自动切换到备用的接口地址,并保证后续所有的请求都…...
多租户架构的全景分析(是什么?基本概念、实现策略、资源管理和隔离、数据安全与隔离、性能优化、扩展性与升级、案例研究)
文章目录 1. 多租户的基本概念2. 多租户的实现策略2.1 独立数据库模式2.2 共享数据库-独立Schema模式2.3 共享数据库-共享Schema模式 3. 资源管理和隔离4. 数据安全与隔离5. 性能优化6. 扩展性与升级7. 案例研究总结 多租户架构在云计算和SaaS应用中越来越流行,因为…...
Git使用问题汇总附带解决方法(持续更新)
Git使用问题汇总附带解决方法 一 git pull 代码时报错: Auto packing the repository in background for optimum performance. See “git help gc“ 一 git pull 代码时报错: Auto packing the repository in background for optimum performance. See …...

Spring Boot驱动的植物健康监测革命
1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理植物健康系统的相关信息成为必然。开发合适…...
element 中 el-dialog 在不同的文件中使用
在实际中工作,我们经常需要使用 el-dialog 来做一个弹框的功能。最常见的就是在父组件中点击一个按纽,然后弹出一个框。而这个框就是子组件。同时,父子组件是分布在不同的文件中。 <!--父组件--> <template> <div> <…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...