一个UDP下载服务器的实现(模拟下载文件)
本期分享的主要是使用UDP实现文件下载功能,需要自己编写服务器和客户端,实现的功能主要有以下几个:
(1)服务器可以为请求的用户下发文件数据(前提是服务器得有这个数据文件)
(2)客户端请求下载数据文件
下面带大家来认真分析下,大家可以对照我遇到的问题是不是大家有遇到,避免大家踩坑,server端代码如下:
首先当然还是头文件部分,没这个可不行呀,哈哈:
#ifndef __HEAD_H__
#define __HEAD_H__#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>#endif
1.接下来看一下具体server的代码实现:
#include "head.h"struct sockaddr_in senaddr;//存放服务器的Ip以及端口号的结构体
int bindOfIP(const char *pIp, int Port) //绑定服务器的ip和端口
{int sockfd = 0;int ret = 0;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("fail to sockfd");return -1;}senaddr.sin_family = AF_INET;senaddr.sin_port = htons(Port);senaddr.sin_addr.s_addr = inet_addr(pIp);ret = bind(sockfd, (struct sockaddr *)&senaddr, sizeof(senaddr));if (-1 == ret){perror("fail to bind");return -1;}return sockfd;
}
以下是发送文件的模块,自从用了UDP发送数据才知道了IO的部分还比较欠缺,那么来看下那一部分有问题:
(1)当选择fread去读取文件的时候(第二个参数设置为1,也就是每次读取成员的大小一个字节),一定要知道它的返回值就是是成功读取文件字节的个数;只有当参数不是1的时候,那么返回值就是成功读取成员的个数;但是最终读取的成员最终还是存放在了我们定义的第一个参数中了;
ret = fread(tmpbuff, 1, sizeof(tmpbuff), fp);
因此在sendto的第三个参数中我们恰好可以使用fread的返回值;
sendto(sockfd, tmpbuff, ret, 0, sendaddr, len);
(2)不使用字节进行传输时,不能在sendto时把第三个变量换位strlen(tmpbuff),因为二进制文件不允许strlen;
int sendFile(char *filename, int sockfd, struct sockaddr *sendaddr, socklen_t len)
{FILE *fp = NULL;char tmpbuff[4096] = {0};ssize_t ret = 0;char *ptmp = NULL;fp = fopen(filename, "r");if (NULL == fp){perror("fail to fopen");return -1;}printf("开始发送!\n");while(1){memset(tmpbuff, 0, sizeof(tmpbuff));ret = fread(tmpbuff, 1, sizeof(tmpbuff), fp);if (ret <= 0){break;}ret = sendto(sockfd, tmpbuff, ret, 0, sendaddr, len);if (-1 == ret){perror("fail to sendto");return -1;}}memset(tmpbuff, 0, sizeof(tmpbuff));sprintf(tmpbuff, "__quit__");ret = sendto(sockfd, tmpbuff, strlen(tmpbuff), 0, sendaddr, len);if (-1 == ret){perror("fail to sendto");return -1;}return 0;
}int main(int argc, const char *argv[])
{int sockfd = 0;char filename[32] = {0};ssize_t nsize = 0;socklen_t len = sizeof(senaddr);int ret = 0;sockfd = bindOfIP("192.168.209.128", 50000);while (1){nsize = recvfrom(sockfd, filename, sizeof(filename), 0, (struct sockaddr *)&senaddr, &len);if (-1 == nsize){perror("fail to recvfrom");return -1;}else{printf("请求的文件名和路径:filename = %s\n", filename);ret = sendFile(filename, sockfd, (struct sockaddr *)&senaddr, len);if (0 == ret){printf("发送成功!\n");}}}return 0;
}
2.下面来看一下client端的实现:
#include "head.h"struct sockaddr_in recvbuf;
int bindOfIP(const char *pIp, int Port)
{int sockfd = 0;int ret = 0;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("fail to sockfd");return -1;}recvbuf.sin_family = AF_INET;recvbuf.sin_port = htons(Port);recvbuf.sin_addr.s_addr = inet_addr(pIp);ret = bind(sockfd, (struct sockaddr *)&recvbuf, sizeof(recvbuf));if (-1 == ret){perror("fail to bind");return -1;}return sockfd;
}
//接收服务器的文件
int recvFile(int sockfd, char *filename)
{FILE *fp = NULL;char tmpbuff[4096] = {0};ssize_t nsize = 0;printf("进来了\n");fp = fopen(filename, "w");if (NULL == fp){perror("fail to fopen");return -1;}while (1){memset(tmpbuff, 0, sizeof(tmpbuff));nsize = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0, NULL, NULL);if (nsize <= 0){break;}if (!strcmp("__quit__", tmpbuff)){break;}fwrite(tmpbuff, sizeof(char), nsize, fp);fflush(fp);}fclose(fp);return 0;
}int main(int argc, const char *argv[])
{int sockfd = 0;char filename[32] = {0};char *name = NULL;ssize_t nsize = 0;socklen_t len;struct sockaddr_in senaddr;int ret = 0;// sockfd = bindOfIP("192.168.209.129", 50001);如果需要可以绑定自己的IP地址和端口sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("fail to sockfd");return -1;}senaddr.sin_family = AF_INET;senaddr.sin_port = htons(50000);senaddr.sin_addr.s_addr = inet_addr("192.168.209.128");while (1){printf("请输入您需要下载的文件路径:");gets(filename);nsize = sendto(sockfd, filename, strlen(filename), 0, (struct sockaddr *)&senaddr, sizeof(senaddr));if (-1 == nsize){perror("fail to sendto");return -1;}name = filename + strlen(filename) - 1;while (*name != '/'){--name;}++name;//解析出文件名printf("name = %s\n", name);//调试代码ret = recvFile(sockfd, name);if (0 == ret){printf("接收成功!\n");break;}}return 0;
}
这个就是一个简单的UDP下载服务器的实现,其实也是很简单的,但是需要注意的细节还是很多的,能提高对IO操作以及UDP通信的深入了解;不懂就问,欢迎评论区留言哦!
相关文章:
一个UDP下载服务器的实现(模拟下载文件)
本期分享的主要是使用UDP实现文件下载功能,需要自己编写服务器和客户端,实现的功能主要有以下几个: (1)服务器可以为请求的用户下发文件数据(前提是服务器得有这个数据文件) (2&…...
01.hadoop上课笔记之hadoop介绍
1.大数据介绍 可以对未来数据预测 google通过搜索预测流感,足球球员有一 定关联…caict可以得到数据hbase hive林子雨mooc数据要进行挖掘(推断更多信息) 2.大数据是非结构化数据多:声音,图片… 3.大数据影响因素 大多快低 tb pb eb zb 1.硬件 2.网络带宽 4.大数据的特征 数据量…...
小鹏汽车Q1财报:押注G6、大力降本,明年智驾BOM降半
作者 | 德新编辑 | 王博 小鹏汽车本周发了Q1财报,数据不好看,以致于在微博端也发了公开信。 那后续呢? 小鹏第二季度指引是,总交付数量约为2.1 - 2.2万辆,收入预计约为45 - 47亿元;四季度,…...
VMware ESXi 8.0U1a 发布 - 领先的裸机 Hypervisor
VMware ESXi 8.0U1a 发布 - 领先的裸机 Hypervisor 请访问原文链接:https://sysin.org/blog/vmware-esxi-8-u1/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 2023-06-01, VMware vSphere 8.0U1a 发布。 详见&am…...
Unity的IPreprocessBuild:深入解析与实用案例
Unity IPreprocessBuild Unity IPreprocessBuild是Unity引擎中的一个非常有用的功能,它可以让开发者在构建项目时自动执行一些操作。这个功能可以帮助开发者提高工作效率,减少手动操作的时间和错误率。在本文中我们将介绍Unity IPreprocessBuild的使用方…...
htmlCSS-----CSS选择器(下)
目录 前言: 2.高级选择器 (1)子代选择器 (2)伪类选择器 (3)后代选择器 (4)兄弟选择器 相邻兄弟选择器 通用兄弟选择器 (5)并集选择器 &am…...
RDK X3 Module发布,全新软硬件平台加速实现量产级产品落地
机器人开发是一段美妙的旅程。GEEKROS创始人杨状状是地平线社区的一名开发者,热衷于鼓捣各类机器人,2022年,状状第一时间就拿到了地平线旭日X3派(简称旭日X3派),基于TogetheROS™.Bot机器人操作系统&#x…...
【面试实战】Redis缓存设计
文章目录 Redis缓存出现的问题🙎♂️面试官:什么是缓存雪崩?🙎♂️面试官:怎样解决缓存雪崩?🙎♂️面试官:什么是缓存击穿?🙎♂️面试官:怎样解决缓存击穿?🙎♂️面试官:什么是缓存穿透?🙎♂️面试官:怎样解决缓存穿透?🙎♂️面试官:…...
如何解决js定时器不准确问题
为什么会出现定时器不准确呢? 这个其实就得提到js执行机制了,叫做事件循环Eventloop 循环机制中,异步事件 setInterval 到时后会把回调函数放入消息队列中Event Queue,主线程的宏任务执行完毕后依次执行消息队列的微任务ÿ…...
学习笔记——vue中使用el-dropdown组件报错
今天在工作中,发现使用el-select做的下拉框,下拉菜单展开后,鼠标点击下拉框之外的区域时,下拉菜单没有收起。然后,我打开控制台,发现了这个错误。 Uncaught TypeError: Cannot read properties of null (re…...
Java之旅(八)
Java 条件运算符 Java 条件运算符用于根据一个条件表达式的布尔值来决定程序执行的流程。条件运算符有三种类型:if、else 和 switch。 if 语句的一般格式如下: if (condition) {// 条件为 true 执行的代码块 } 其中,condition 是一个 bool…...
华为OD机试真题(Java),四则运算(100%通过+复盘思路)
一、题目描述 输入一个表达式(用字符串表示),求这个表达式的值。 保证字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。 数据范围:表达式计算结果和过程中满足∣val∣≤1000 ,字符串长度满…...
HTML表单标签form分析
说明:在html的标签中,表单标签与后台联系密切,像用户登录、注册,都是用到页面的表单标签,用户将信息填入到表单中,提交到后端业务中校验处理,再将结果反馈给前端页面。 表单内的标签分别有&…...
Qt 项目文件Pri详解
在Qt项目中,pri文件(.pri)是一种类似于makefile的文件,用于定义Qt项目中的编译规则。通常可以用pri文件来配置Qt库、头文件、源文件、链接库等信息,这样可以把这些信息定义在一个文件中,避免在每个工程中都进行重复配置࿰…...
Keil 5 MDK 发律师函警告了,如何用STCubeIDE开发标准库的程序(STM32F103C8T6为例)
用STCubeIDE进行标准库开发 1、CubeIDE介绍 https://www.stmcu.com.cn/ecosystem/Cube/STM32CubeIDE 2、CubeIDE下载 点击上面的链接,登录即可下载 3、搭建Demo工程 新建一个工作空间 创建一个工程 选择芯片-STM32F103C8T6 填写工程信息 添加标准库到工程 标…...
接口测试--apipost接口断言详解
在做接口测试的时候,会对接口进行断言,一个完整的接口测试,包括:请求->获取响应正文->断言。 一、apipost如何进行断言 apipost的断言设置实在后执行脚本中进行编写的。apipost本身提供了11中断言: apt.asser…...
YYDS练手 130道python练习题 完整版PDF
近年来,Python在编程语言界里赚足了风头,无论是受欢迎程度,还是薪资待遇,都非常可观,相应的,Python岗位要求也越来越高,无论你是零基础还是老前辈,在Python面试中都不能轻视。 不打…...
2-python的变量类型
内容提要 主要回顾了python中的变量类型,区分它们和c中的区别 python中的数字没有long python中的字符串不能被改变,也就是说不能对其内字符元素进行赋值操作 python中列表的数据类型与c访问方式有一定的区别列表的下标可以是负数,无论正负&…...
Python之并发编程一背景知识
一、开篇介绍 顾名思义,进程即正在执行的一个过程。进程是对正在运行程序的一个抽象。 进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一。操作系统的其他所有内容都是围绕进程的概念展…...
Redis分区
分区 Redis是单线程的,如何提高多核CPU的利用率? 可以在同一个服务器部署多个Redis的实例,并把他们当作不同的服务器来使用,在某些时候,无论如何一个服务器是不够的, 所以,如果你想使用多个CPU&…...
PwnKit漏洞深度解析:pkexec环境变量劫持与Linux提权原理
1. 这个漏洞不是“又一个提权”,而是Linux权限模型的照妖镜你可能已经看过不少关于CVE-2021-4034的通报,标题里常带着“高危”“远程可利用”“影响所有主流发行版”这类字眼。但说实话,我第一次在Debian 11上复现成功时,并没有立…...
5分钟掌握SVGnest:免费开源矢量嵌套工具,让材料切割效率提升80%
5分钟掌握SVGnest:免费开源矢量嵌套工具,让材料切割效率提升80% 【免费下载链接】SVGnest An open source vector nesting tool 项目地址: https://gitcode.com/gh_mirrors/sv/SVGnest SVGnest是一款完全免费且开源的自动嵌套应用程序,…...
鸿蒙electron跨端框架PC简序实战:把轻任务、优先级和截止时间塞进一张桌面清单
前言 欢迎加入鸿蒙PC开发者社区,共同打造开发者工具生态:鸿蒙PC开发者社区 :https://harmonypc.csdn.net/ 开源地址:https://AtomGit.com/lqjmac/ele-shixu?source_modulesearch_project 写 简序 时,我没有把它当成…...
30岁之后IT人士(程序员)的职业规划是什么呢?
前段也看到ibm的寇卫东的一篇文章关于职业规划的,现在看看,这些职业规划都是理想状态下的产物,很多时候,限于我们自身水平、时间、空间的影响,很多是看着很美,其实却远远的达不到,不能仅仅说让人…...
基于VSCode与CMake的G32R501 MCU现代化开发环境搭建实战
1. 项目概述:为什么选择这套组合拳? 最近在折腾极海半导体的G32R501这款MCU,发现身边不少朋友在搭建开发环境时,要么被臃肿的IDE拖慢速度,要么在构建配置上反复踩坑。我自己的习惯是,能用轻量化工具链搞定的…...
别再只会用`docker system prune`了!聊聊Docker磁盘清理的5个隐藏场景与实战命令
别再只会用docker system prune了!聊聊Docker磁盘清理的5个隐藏场景与实战命令 Docker作为现代开发与运维的核心工具,其便捷性背后往往隐藏着磁盘管理的复杂性。当docker system prune成为大多数人的清理"万能药"时,真正棘手的磁盘…...
FCEUX:专业级NES模拟器的深度探索与实战应用
FCEUX:专业级NES模拟器的深度探索与实战应用 【免费下载链接】fceux FCEUX, a NES Emulator 项目地址: https://gitcode.com/gh_mirrors/fc/fceux 🚀 在复古游戏复兴与技术考古的浪潮中,FCEUX以其卓越的专业性脱颖而出,成为…...
用户测试完整流程:如何在测试阶段验证产品假设
用户测试完整流程:如何在测试阶段验证产品假设 【免费下载链接】design-sprint Product Design Sprint Material 项目地址: https://gitcode.com/gh_mirrors/de/design-sprint 在产品开发过程中,用户测试是验证产品假设、确保产品满足用户需求的关…...
sdk-manager-plugin源码剖析:学习Gradle插件架构的完美案例 [特殊字符]
sdk-manager-plugin源码剖析:学习Gradle插件架构的完美案例 🚀 【免费下载链接】sdk-manager-plugin DEPRECATED Gradle plugin which downloads and manages your Android SDK. 项目地址: https://gitcode.com/gh_mirrors/sd/sdk-manager-plugin …...
紧急预警:传统ML Ops正被Agent-native ML取代!3类组织已启动迁移,你还在手动调参?
更多请点击: https://kaifayun.com 第一章:AI Agent机器学习应用的范式跃迁 传统机器学习系统通常以静态模型为中心,依赖人工特征工程、固定训练-推理流水线与离线评估闭环。而AI Agent的兴起正推动一场根本性范式跃迁:从“被动预…...
