基于TCP协议的文件传输系统
最简单的一对一的服务端网络端通信(socket)
Socket=(IP地址:端口号),例如:如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23)
socket可以理解成计算机提供给程序员的接口,数据在客户端和服务端之间的socket之间传输。socket把复杂的TCP/IP协议封装,对于程序员来说只要利用好函数,就可以实现数据通信。
TCP提供了stream和datagram两种通信机制,所以socket分这两种。
stream的类型是SOCK_STREAM,采用TCP协议,TCP协议在计算机网络中是安全可靠的有连接的协议。datagram的类型是SOCK_DGRAM,采用的是UDP协议,UDP是不可靠的协议,现在在实际应用开发中,主要采用的是TCP。
服务端主要流程:创建socket—bind绑定ip和port—listen监听客户端连接请求—accept接受连接----数据传输----close关闭连接
int listenfd;listenfd=socket(AF_INET,SOCK_STREAM,0);//在socket编程中,AF_INET是必须的,等同于固定搭配//socket创建成功后如果返回值是-1的话,说明创建失败,为0的时候就是创建成功if(listenfd==-1){printf("socket create fail\n");return -1;}
struct sockaddr_in serveraddr;//定义一个用来处理网络通信的数据结构,sockaddr_in分别将端口和地址存储在两个结构体中//sin_family协议族memset(&serveraddr,0,sizeof(serveraddr));serveraddr.sin_family=AF_INET;serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);//serveraddr.sin_addr.s_addr=atoi(argv[1]);// specify ip addressserveraddr.sin_port=htons(atoi(argv[1]));//specify port//printf("%s %s\n",argv[1],argv[2]);if(bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr))!=0){printf("bind failed \n");return -1;}
INADDR_ANY 表示监听0.0.0.0地址,socket只绑定端口,不绑定本主机的某个特定ip,让路由表决定传到哪个ip(0.0.0.0地址表示所有地址、不确定地址、任意地址)(一台主机中如果有多个网卡就有多个ip地址)
htons()把short型值转成按网络字节顺序排列的short型值
htonl()把long型值转成按网络字节顺序排列的long型值
假设你已经有了一个sockaddr_in结构体ina,你有一个IP地址"132.241.5.10" 要储存在其中,你就要用到函数inet_addr(),将IP地址从 点数格式转换成无符号长整型。使用方法如下:
ina.sin_addr.s_addr = inet_addr(“132.241.5.10”);
if(listen(listenfd,5)!=0){printf("Listen failed\n");close(listenfd);return -1;}
backlog 5 是未经过处理的连接请求队列可以容纳的最大数目。
int clintfd;//socket for clientint socklen=sizeof(struct sockaddr_in);struct sockaddr_in client_addr;clintfd=accept(listenfd,(struct sockaddr*)&client_addr,(socklen_t *)&socklen);if(clintfd==-1)printf("connect failed\n");elseprintf("client %s has connnected\n",inet_ntoa(client_addr.sin_addr));
inet_ntoa将网络地址转换成“.”点隔的字符串格式。char buffer[1024];while (1){int iret;memset(buffer,0,sizeof(buffer));iret=recv(clintfd,buffer,sizeof(buffer),0);if (iret<=0) {printf("iret=%d\n",iret); break; }printf("receive :%s\n",buffer);strcpy(buffer,"ok");//reply cilent with "ok"if ( (iret=send(clintfd,buffer,strlen(buffer),0))<=0) { perror("send"); break; }printf("send :%s\n",buffer);}// 6th close socketclose(listenfd); close(clintfd);
对于服务端来说有两个socket,这里该如何理解呢?
一开始socket函数, 不管在客户端还是在服务端, 创建的都是主动socket, 但是在服务端经过listen(), 后把其转变为listen_socket_fd(被动监听socket),经过accept()后转变为connect_socket_fd(已连接socket).
在转变为connect_socket_fd之前, 都是同一个socket, 只不过是socket的状态改变了, 但是服务端经过accept()后返回的socket是新的socket, 用于连接后的read()/write()
假设只用一个socket完成整个过程. 那么这个socket就会一直被占用, 而不能被另外的客户端请求, 造成了服务端的性能极其低下, 如果没有存储后面的客户端请求, 就会被错过而丢弃, 因为当前的socket正在与当前一个客户端的socket建立连接.
客户端 socket-connect
struct sockaddr_in servaddr;memset(&servaddr,0,sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(atoi(argv[2])); // server's portservaddr.sin_addr.s_addr=inet_addr(argv[1]);//server's ipif (connect(sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr)) != 0) // send request to server for connection{ perror("connect"); close(sockfd); return -1; }
多进程的(一个服务端服务多个客户端)

具体实现就是:在accept部分增加一个外层的循环,
子进程执行完之后就return 0或者exit(0),直接退出去。
还有一个问题就是:查看打开的进程编号可以发现,父进程和子进程文件描述符一样的。对于父进程来说,只需要监听连接,不需要连接后的fd;对子进程来说,listenfd也是不需要的。但是fork会生成一份副本,导致父子进程都有listenfd和connectfd,所以可以在父进程中关掉connectfd,子进程中关掉listenfd。为什么要这么做,因为fd是一种资源,维护一个fd不难,但是很多客户端就会有很多冗余的fd,造成资源浪费。而且一个进程能打开的fd是有限的。
多进程服务程序的退出

子进程收到退出信号(ctrl+c),在子进程设置signal(2,childexit),signal(15,childexit)。然后子进程关闭客户端的fd再退出。
父进程会关闭listenfd,然后通知所有子进程退出,然后退出。
TCP长连接和心跳机制的实现
短连接:
短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接(管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段);
连接→数据传输→关闭连接;
所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持(不发生RST包和四次挥手)。
连接→数据传输→保持连接(心跳)→数据传输→保持连接(心跳)→……→关闭连接(一个TCP连接通道多个读写通信);
长连接多用于操作频繁(读写),点对点的通讯,而且连接数不能太多情况。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。
而像WEB网站的http服务一般都用短链接(http1.0只支持短连接,1.1keep alive 带时间,操作次数限制的长连接),因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好;
具体实现:
服务端和客户端约定超时时间,假设35秒;
如果服务端35秒没收到报文,认为客户端异常,主动关闭;
客户端35秒内没有任何业务,发送心跳报文,以维持连接。
客户端在空闲时发送心跳报文,服务端的读函数增加一个超时参数,超时就断开连接,不超时就回复成功。
实现文件的上传和下载功能、异步通信机制实现快速传输。
主要包含:文件传输的服务端模块(支持上传下载) 文件上传的客户端,文件下载的客户端。
客户端分成两个是因为让程序结构更简单,模块化;服务端不分开因为它是网络服务程序,分成两个的话就要两个监听的端口,配置网络参数更麻烦,比如路由器防火墙。
文件上传客户端:登录(意义在于协商与服务端协商文件传输参数,最重要参数就是文件存放目录,客户端的A目录存在服务端的B目录)
客户端获取本地目录的文件清单,假设有100个文件,一个循环,每次先传文件信息(名字,大小,时间),再传内容。
结束后客户端休息几秒,再重新获取本地目录的文件清单。
注意:用于系统内部文件传输,所以客户端程序常驻内存,每隔几秒就传输一次。客户端上传成功后直接删除本地文件就可以。
定义一个结构体存储心跳,目录等信息。

服务端只要之前的参数就可以,客户端通过登录报文将更多的参数传到服务端。

服务端再修改相应的代码。处理登录报文,如果是1,就完成上传功能主函数。

首先服务端调用_xmltoarg方法解析登录报文,如果是1或者2,发送ok给客户端,否则发送failed给客户端。如果登陆失败(美没收到服务端回应),直接退出。
如果类型为1,调用RecvFilesMain()
void RecvFilesMain()
{while(true){ memset(recvbuf,0,sizeof(recvbuf));memset(sendbuf,0,sizeof(sendbuf));如果接收客户端的报文read失败(超时),记录日志,return;如果接收缓存内容是心跳报文,给客户端回复ok;处理上传文件的请求报文}}
客户端文件信息的上传怎么实现?

服务端怎么处理这些信息

传输文件的内容
sendfile函数实现。参数有连接的socketfd,文件名,文件大小。


异步通讯三种实现方法:
1、多进程:服务端客户端后,fork一个子进程,子进程负责接收信息,父进程发送信息,
2、多线程。
3、I/O复用技术
同步的话客户端发送报文,要等到接受ok再发送第二个,10000个数据需要6秒。异步的话,父进程发送报文,子进程接受ok的成功信息,1秒。
如果是10万的话,同步每秒2000左右,异步每秒8万左右。
I/O复用就是没有数据的话不等待,直接返回。每秒差不多6万,低一点,原因就是有数据的话会等待数据搞完再发送,当然低一点。
相关文章:
基于TCP协议的文件传输系统
最简单的一对一的服务端网络端通信(socket) Socket(IP地址:端口号),例如:如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23) socket可以理解成计算机提供给程序员的接…...
Linux定时备份MySql数据库
一、创建文件 cd / mkdir mysqlbackup vi mysqlbackup.sh然后将下面的代码更改后复制上去即可。 #!/bin/bash mysqldump -uroot -ppassword database > /mysqlbackup/database__$(date %Y%m%d_%H%M%S).sqlpassword指的是MySql的密码,database指的是所要备份的…...
JavaScript prototype(原型对象)
JavaScript 的原型(prototype)是 JavaScript 中的一个重要概念。它是一种特殊类型的对象,每个 JavaScript 对象都有一个原型对象。原型对象在 JavaScript 中起着非常重要的作用。本文将详细介绍 JavaScript 原型对象的作用和在实际工作中的用…...
pytorch各种版本最简单安装,不用自己安装cuda cudnn
pytorch各种版本 pip 安装命令 查看官网 https://pytorch.org/get-started/previous-versions/ conda pytorch 安装 1、安装conda, 2、创建并并激活虚拟环境 - conda create -n pytorch_1.7 python3.7 - conda activate pytorch_1.7 3、虚拟环境中 pip 安装想要的…...
订单超时处理方案介绍
在电商场景下,一个订单流程中有许多环节要用到超时处理,包括但不限于: 买家超时未付款:比如超过15分钟没有支付,订单自动取消。 商家超时未发货:比如商家超过1个月没发货,订单自动取消。 买家…...
Blackbox-Exporter对服务进行探活
前言 blackbox-exporter会对HTTP、HTTPS、DNS、TCP、ICMP和gRPC上的端点进行黑盒探测。 Blackbox-Exporter blackbox-exporter暴露两个Metrics指标接口,分别是 /metrics、/probe,两个接口返回不同监控目标的指标 Metrics接口 返回exporter的构建信息…...
react-redux
Redux 是js容器,用于进行全局的 状态管理它可以用在react, angular, vue等项目中, 但基本与react配合使用三大核心: 单一数据源 整个应用的state被存储在一棵 object tree中,并且这个 object tree只存在于一个唯一的 store 中 State是只读的…...
算法刷刷刷| 回溯篇| 子集问题大集合
78.子集 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入:nums [1,2,3] 输出:[[],[1],[2],[1…...
合并两个有序数组-力扣88-java
一、题目描述给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。注意:最终,合…...
2022「大厂可观测」重磅回顾,12场直播,15位技术大咖洞见可观测
回首2022年,注定是意义非凡的一年。新冠疫情继续肆虐全球,中国疫情全面放开,神舟十四号与神舟十五号成功会师,俄乌冲突带来深远影响,阿根廷再次问鼎世界杯梅西圆梦,英国女王逝世......件件事都备受关注。 …...
CMMI-配置管理(CM)
一、概述配置管理(Configuration Management, CM)的目的在于使用配置识别、配置控制、配置状态记录与报告以及配置审计,来建立并维护工作产品的完整性。1、简介“配置管理”过程域涉及以下活动:• 识别所选工作产品的配…...
网络编程套接字Socket
一.什么是网络编程网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。二.为什么要实现网络编程我们通过网络编程可以在网络中获取资源,实质是通过网络,获…...
Linux进程概念(二)
进程状态1.阻塞和挂起2.R运行状态和S睡眠状态3.T停止状态4.X死亡状态和Z僵尸状态🌟🌟hello,各位读者大大们你们好呀🌟🌟 🚀🚀系列专栏:【Linux的学习】 📝📝本…...
墨天轮【第二届数据库掌门人论坛】圆满收官 | 含嘉宾精彩观点回顾
2月10日上午,墨天轮【2023春季发布会暨第二届数据库掌门人论坛】盛大开启,本次活动的主题为“新征程,向未来”,共包含2022年度中国数据库颁奖盛典、2022年度行业发展报告发布以及第二届数据库掌门人论坛三项议程。华为云数据库服务…...
Redis之集群搭建
redis的集群模式简介: redis的集群模式中可以实现多个节点同时提供写操作,redis集群模式采用无中心结构,每个节点都保存数据,节点之间互相连接从而知道整个集群状态。 集群搭建步骤如下 (一台服务器模拟多台服务器) 1.创建6个配置…...
31-Golang中的二维数组
二维数组的使用方式 使用方式一:先声明/定义再赋值 1.语法:var数组名 [大小] [大小]类型2.比如:var arr [2] [3]int,再赋值 package main import ("fmt" )func main() {//定义/声明数组var arr [4][6]int//赋初值arr[1][2] 1ar…...
<<Java开发环境配置>>6-SQLyog安装教程
一.SQLyog简介: SQLyog 是一个快速而简洁的图形化管理MySQL数据库的工具,它能够在任何地点有效地管理你的数据库,由业界著名的Webyog公司出品。使用SQLyog可以快速直观地让您从世界的任何角落通过网络来维护远端的MySQL数据库。 二.SQLyog下载: 下载地址…...
MySQL 中的 distinct 和 group by 哪个效率更高
先说大致的结论(完整结论在文末):在语义相同,有索引的情况下:group by和distinct都能使用索引,效率相同。在语义相同,无索引的情况下:distinct效率高于group by。原因是distinct 和 …...
计算机相关专业毕业论文选题推荐
计算机科学以下是我推荐的20个计算机科学专业的本科论文选题:基于机器学习的推荐算法研究与实现基于区块链技术的数字身份认证方案设计与实现基于深度学习的图像识别技术研究与应用基于虚拟现实技术的教育培训平台设计与实现基于物联网技术的智能家居系统研究与开发…...
网络编程套接字之TCP
文章目录一、TCP流套接字编程ServerSocketSocketTCP长短连接二、TCP回显服务器客户端服务器客户端并发服务器UDP与TCP一、TCP流套接字编程 我们来一起学习一下TCP socket api的使用,这个api与我们之前学习的IO流操作紧密相关,如果对IO流还不太熟悉的&am…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
