c++ udp多线程 例子_[内附完整源码和文档] 基于udp实现tcp功能进行大文件传输

一.项目要求
Please choose one of following programing languages: C, C++, Java, Python;
本项目采用的是python3.6
LFTP should use a client-server service model;
本项目使用客户端-服务器的模式
LFTP must include a client side program and a server side program; Client side program can not only send a large file to the server but also download a file from the server.
Sending file should use the following format:
LFTP lsend myserver mylargefile
Getting file should use the following format
LFTP lget myserver mylargefile
The parameter myserver can be a url address or an IP address.
本项目,客户端不仅可以向服务器上传大文件,也可以从服务器下载大文件
LFTP should use UDP as the transport layer protocol.
本项目利用UDP来作为传输层协议
LFTP must realize 100% reliability as TCP;
本项目实现类似TCP的100%可靠性,处理了丢包,超时,数据包顺序不一致等问题
LFTP must implement flow control function similar as TCP;
本项目实现了类似TCP的流控制,在接收方维护一个rwnd接收窗口
LFTP must implement congestion control function similar as TCP;
本项目实现了类似TCP的阻塞控制,在发送方维护一个cwnd阻塞窗口
LFTP server side must be able to support multiple clients at the same time;
本项目支持多个用户同时向服务器收发文件,使用了多线程的机制
LFTP should provide meaningful debug information when programs are
executed.
本项目提供了有意义的debug消息来显示发送情况,包括丢包,阻塞等事件的处理
二. 设计思路
基于UDP的传输过程如下图所示:

5e6c1108afab4aafbfdde4ef549f0f24.png


基于UDP来实现类似TCP的大文件传输,代码构建过程:

利用socket实现简单字符串传送

对于文件进行处理,将1的代码改造成文件的传送

对于文件进行分段,打包发送

发送过程使用多线程

服务器与客户端连接的建立与断开,三方握手,四次挥手

处理命令行输入命令,与服务器进行交互

添加ACK反馈包,建立判断重复ACK机制

丢包事件的判断与处理

接收方的序列号是否正确,要求重发

接收方的流控制,构建接收窗口

发送方的阻塞控制

三. 模块设计
3.1 设置传送数据包的数据结构,以及反馈包的数据结构
这里的数据包与反馈包结构我采用的是struct结构体,其中一个数据包所带有文件数据为1024bytes,而头文件包括序列号,确认号,文件结束标志,为24bytes。

反馈包包括ack确认,rwnd接收窗口的大小。

传送一个包的结构,包含序列号,确认号,文件结束标志,数据包

packet_struct = struct.Struct(‘III1024s’)

接收后返回的信息结构,包括ACK确认,rwnd

feedback_struct = struct.Struct(‘II’)
BUF_SIZE = 1024+24
FILE_SIZE = 1024
3.2 服务器部分:处理客户端传输的命令,并使用多线程来处理
服务器先建立一个主的线程来监听接收客户端到来的命令,将命令接收后传送到server_thread来处理,传递的参数包括客户端的命令参数以及客户端的地址。

···
IP = ‘192.168.88.129’
SERVER_PORT = 7777
···
def main():
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 绑定端口:
s.bind((IP, SERVER_PORT))
while True:
data,client_addr = s.recvfrom(BUF_SIZE)
# 多线程处理
my_thread = threading.Thread(target=server_thread,args=(client_addr,data))
my_thread.start()
3.3 服务器部分:多线程处理函数
该函数要为每一个客户端新建一个socket,并将命令解析得到客户端所需要的操作

def server_thread(client_addr,string):
# 处理传输过来的str,得到文件名,命令
order = ‘’
try:
order = string.decode(‘utf-8’).split(’,’)[0]
file_name = string.decode(‘utf-8’).split(’,’)[1]
except Exception as e:
return
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
···
除此以外,还需要像TCP建立连接一样来进行三方握手,确认连接才开始发送。

客户端先申请连接

三方握手

发送请求建立连接

s.sendto(data,server_addr)

接收连接允许

print(data.decode(‘utf-8’))
data,server_addr = s.recvfrom(BUF_SIZE)
print(‘来自服务器’, server_addr, '的数据是: ', data.decode(‘utf-8’))
服务器确认连接

文件存在,返回确认信号

s.sendto(‘连接就绪’.encode(‘utf-8’),client_addr)
data,client_addr = s.recvfrom(BUF_SIZE)
print(‘来自’,client_addr,‘的数据是:’,data.decode(‘utf-8’))
客户端再发送确认包,这时连接就建立完毕

第三次握手,确认后就开始接收

data=‘ACK’.encode(‘utf-8’)
s.sendto(data,server_addr)
下面是四次挥手的过程:

当服务器执行完客户端的命令后,要像tcp一样来执行断开连接操作,断开连接后可以把socket释放掉,即调用close函数。

服务器:

print(’n开始中断连接’)

中断连接,四次挥手

data,server_addr = s.recvfrom(BUF_SIZE)
print(data.decode(‘utf-8’))
data = ‘Server allows disconnection’
s.sendto(data.encode(‘utf-8’),client_addr)
print(data)
data = ‘Server requests disconnection’
s.sendto(data.encode(‘utf-8’),client_addr)
print(data)
data,server_addr = s.recvfrom(BUF_SIZE)
print(data.decode(‘utf-8’))
print(‘The connection between client and server has been interrupted’)
s.close()
客户端:

中断连接,四次挥手

data = ‘Client requests disconnection’
print(data)
s.sendto(data.encode(‘utf-8’),server_addr)
data,client_addr = s.recvfrom(BUF_SIZE)
print(data.decode(‘utf-8’))
data,client_addr = s.recvfrom(BUF_SIZE)
print(data.decode(‘utf-8’))
data = ‘Client allows disconnection’
s.sendto(data.encode(‘utf-8’),server_addr)
print(data)
print(‘The connection between client and server has been interrupted’)
s.close()
说完建立连接与断开连接,回到多线程处理函数,对于lsend,lget函数的判断:当命令是lget时,要判断服务器是否存在该文件,如果不存在则直接返回信息后,关闭socket;若存在该文件直接进入lget函数来进行处理。当命令是lsend时,直接进入lsend函数来进行处理。

if order == ‘lget’:
# 处理文件不存在的情况
if os.path.exists(file_name) is False:
data = ‘FileNotFound’.encode(‘utf-8’)
s.sendto(data, client_addr)
# 关闭socket
s.close()
return
# 文件存在,返回确认信号
s.sendto(‘连接就绪’.encode(‘utf-8’),client_addr)
data,client_addr = s.recvfrom(BUF_SIZE)
print(‘来自’,client_addr,‘的数据是:’,data.decode(‘utf-8’))
lget(s,client_addr,file_name)
elif order == ‘lsend’:
s.sendto(‘是否可以连接’.encode(‘utf-8’),client_addr)
# 等待确认
data,client_addr = s.recvfrom(BUF_SIZE)
print(‘来自’,client_addr,‘的数据是:’,data.decode(‘utf-8’))
lsend(s,client_addr,file_name)

846463e99b8cb374cd90dd01ddf09fec.png

9431671d645f3c55cd5517b645a8763e.png

bbe9af6b9a364fb6bfd828c5855a9a04.png

78ebfa46e29d7cb54467a9fb00ceaeb4.png

完整的源码和详细的文档,上传到了 WRITE-BUG技术共享平台 上,需要的请自取:

https://www.write-bug.com/article/2998.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/551571.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jquery设置video的宽度_jquery html5 视频播放控制代码

jQuery HTML5 视频播放控制核心代码:您的浏览器不支持html5!$(video).click(function() {if ($(this).hasClass(pause) ) {$("video").trigger("play");$(this).removeClass(pause);$(this).addClass(play);} else {$("video&q…

C语言中 1%3,算术什么意思啊 算数什么意思

算术什么意思啊 算数什么意思以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!算术是什么意思数学什么是算术和算术和是正数的和,即绝对值的和,例如213.57,…

嘉兴python培训_嘉服集团

请下拉查看…… 嘉服集团工作简报2020年第10期 嘉服集团工作简报2020年第9期 嘉服集团工作简报2020年第8期 嘉服集团工作简报2020年第7期 嘉服集团工作简报2020年第6期 嘉服集团工作简报2020年第5期 嘉服集团工作简报2020年第4期 嘉服集团工作简报2020年第3期 嘉服集团工作简报…

steam有没有c语言软件,【图片】在steam吧你甚至可以讨论c语言_steam吧_百度贴吧...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#include#include /*包含字符串处理函数的头文件,可以直接调用现有的字符串处理的一系列函数了*/#includeusing namespace std;typedef struct //定义结构体{char score; /*编号*/char name[10]; /*姓名*/char num[15];…

c++ vscode 自动注释_WIN下vscode调试C/C++,从零开始生成helloworld项目【2018年6月29日】...

最近迷上了vscode这款编译器,小巧美观,用起来也很顺手,最主要的是全平台,正好最近要上手做Linux C客户端,以前没接触过linux,先拿它先在WIN上练练手。这几天在网上找了非常多的教程,win总是配不…

AVR单片机计算器C语言源程序,一个基于AVR单片机的计算器程序.doc

一个基于AVR单片机的计算器程序#include#include//延时函数的头文件#include // 中断函数的头文件#define uint unsigned int#define uchar unsigned char#define BIT(k) (1<#define DI PORTC //夜晶的数据输入端#define No_key 255//没有按键按下的返回值#define key_port …

python 消息框但不影响程序执行_还在用print()查找错误?日志消息不香嘛?| 原力计划...

作者 | 灰小猿责编 | 王晓曼出品 | CSDN博客最近在做项目开发的时候&#xff0c;跟小伙伴聊到修 Bug 这件事。嗯&#xff0c;对于一只没技术的程序猿来说&#xff0c;修 Bug 的确是一件让人头疼的事情&#xff0c;尤其是对于比较大型的项目开发&#xff0c;在变量较多的时候&am…

vue中传值和传引用_vue prop属性传值与传引用示例

vue prop属性传值与传引用示例vue组件在prop里根据type决定传值还是传引用。简要如下&#xff1a;传值&#xff1a;String、Number、Boolean传引用&#xff1a;Array、Object若想将数组或对象类型也以值形式传递怎么办呢&#xff1f;如下方式可以实现&#xff1a;// component-…

.sql文件_Mysql分组排序及Sql文件执行

最近在做一个临时项目&#xff0c;采用的是mysql开发&#xff0c;主要涉及两个问题&#xff1a;1.一个是传参问题&#xff1b;2.另一个是实现对数据分组取前4的数据。个人感觉很有意义&#xff0c;特此记录一下。一.传参问题执行mysql文件&#xff0c;需要从外部传入参数时&…

laravel 异常捕获_Laravel框架捕获各种类型错误

Laravel 中的所有异常都由类App\Exceptions\Handler集中处理&#xff0c;这个类有两个方法&#xff1a;report 和 render。【report 方法】report 方法用于记录异常并将其发送给外部服务。默认情况下&#xff0c;report 方法只是将异常传递给异常基类并写入日志进行记录&#x…

android 动态库 后缀,Android Robolectric加载运行本地So动态库

前言Robolectric 是 Android 的单元测试框架&#xff0c;运行无需 Android 真机环境直接运行在 JVM 之上&#xff0c;所以在 test case 运行速度效率上有了很大提升&#xff0c;接近于 Java JUnit test(JUnit test > Robolectric ≫ androidTest)。不过框架本身并不支持 so …

java web输出语句到控制台_Java工程师(6).循环结构

搞清楚循环结构语句的执行效果与使用场景。程序中的循环流程程序中的循环流程试着编写程序实现下列功能&#xff1a;在控制台中输出100个Hello字符串。在控制台中输出从 1 到 100 的数字。… …循环结构的三要素循环结构必然包含如下三要素&#xff1a;循环变量 &#xff08;循…

sap生产工单报工_SAP系统PP (ProductionPlanning) 模块知识培训

SAP系统PP(ProductionPlanning)模块知识培训主要内容为支持生产系统规范使用SAP系统开展日常业务&#xff0c;掌握SAP系统常用操作和异常处理的方法&#xff0c;人力资源部在6月10日下午组织实施了一期《SAP系统PP模块知识》的培训。本次培训由信息技术部主管工程师解虎授课&am…

android加载百分比功能,android进度条怎么显示百分比

android布局文件里的ProgressBar长形进度条怎么自 在windows操作系统下Android studio按照如下步骤自动义ProgressBar长形进度条的样式。首先创建一个android项目&#xff0c;打开其中的XML布局文件&#xff0c;如下图&#xff1a;添加ProgressBar控件&#xff0c;如下图&#…

64位程序怎么判断指针是否有效_AArch64应用程序级编程模型

根据实现选择&#xff0c;体系结构支持多级执行特权&#xff0c;由从EL0到EL3的不同异常级别表示。EL0对应于最低的特权级别&#xff0c;通常被描述为无特权。应用层程序员模型是在EL0上执行软件的程序员模型。系统软件决定异常级别&#xff0c;因此决定软件运行的特权级别。当…

n个小球放入m个盒子中_飞么盒子卫生巾自助售卖机前景

嘿&#xff0c;你有没有经历过&#xff0c;出门在外来大姨妈却没带M巾呢&#xff1f;尴尬丛生的你选择怎么做&#xff1f;现在&#xff0c;有了新选择&#xff0c;这也是今天我们迫不及待想要和你们介绍的新朋友—飞么盒子&#xff0c;由Faimes飞么品牌自主研发出品的卫生巾售卖…

Android代码设置角标,Android上的Badge,快速实现给应用添加角标

应用角标是iOS的一个特点&#xff0c;原生Android并不支持。或许是由于当时iOS的通知栏比较鸡肋(固然如今已经改进了不少)&#xff0c;而Android的通知栏功能强大&#xff1f;因此才出现了一方依赖于数字角标&#xff0c;一方坚持强大的通知栏&#xff0c;在平常使用中这两种交…

opencv模糊图像变清晰_opencv-python 4.2图像模糊

图像模糊可以去除噪音。import cv2 import numpy as npimage cv2.imread("dogcat1.jpg") cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE) cv2.imshow("input image", image)#均值模糊 dst cv2.blur(image, (5, 5)) cv2.imshow("…

datatable怎么根据两列分组_公司要IT转型,我该怎么办?用Python进行数据处理

“ 以后数据处理&#xff0c;都用pandas”01 面临问题作为运维人员&#xff0c;每周要统计很多数据&#xff0c;特别是周四写周报的时候&#xff0c;基本要花半天时间。既然已经学了Python&#xff0c;那就试试优化它。以统计不同厂家、不同设备类型告警量为例。需要将多份类似…

C语言非常大的数组,关于最大子数组问题

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼纯新手&#xff0c;最近想学一下算法&#xff0c;上网看了个教程&#xff0c;看到了一个很经典的返回最大子数组之和的问题&#xff0c;然后我想问一下我用分治法把最大和求出来了&#xff0c;但是要怎么返回子数组本身呢&#xff…