基于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…...
无需训练数据!RexUniNLU零样本抽取实战,效果超预期
无需训练数据!RexUniNLU零样本抽取实战,效果超预期 1. 零样本理解:NLP领域的新范式 在传统自然语言处理项目中,我们常常陷入一个困境:为了从文本中抽取特定信息,必须先收集大量标注数据,然后训…...
如何在Netty客户端实现断线自动重连
channelInactive 由于底层资源没有完全释放,不能立即重新连接,需要等待 closeFuture 完成或延迟后 connect;推荐用 HashedWheelTimer 实现指数退出重连,确保 Bootstrap 配置一致,分类处理异常,心跳保存。ch…...
大数据领域实时分析的算法优化策略
大数据领域实时分析的算法优化策略 关键词:大数据、实时分析、算法优化、流处理、增量计算、分布式计算、性能调优 摘要:本文深入探讨大数据实时分析领域的算法优化策略,从核心概念到实际应用,系统性地介绍了流处理架构、增量计算原理、分布式算法优化等关键技术。通过具体…...
【数据分析】基于机器学习增强策略对燃烧不稳定预测进行不确定性量化附matlab代码
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…...
FaceFusion入门到精通:掌握核心参数,告别“塑料脸”和边缘割裂
FaceFusion入门到精通:掌握核心参数,告别"塑料脸"和边缘割裂 1. FaceFusion简介与核心价值 FaceFusion作为新一代AI换脸工具,凭借其开箱即用的特性和强大的硬件兼容性,正在改变数字内容创作的方式。与早期换脸工具相比…...
TypeScript-Node-Starter安全指南:Passport认证与用户权限管理详解
TypeScript-Node-Starter安全指南:Passport认证与用户权限管理详解 【免费下载链接】TypeScript-Node-Starter A reference example for TypeScript and Node with a detailed README describing how to use the two together. 项目地址: https://gitcode.com/gh_…...
高效配置AGENTS.md开发环境:3个提升AI编码代理工作效率的最佳实践
高效配置AGENTS.md开发环境:3个提升AI编码代理工作效率的最佳实践 【免费下载链接】agents.md AGENTS.md — a simple, open format for guiding coding agents 项目地址: https://gitcode.com/GitHub_Trending/ag/agents.md AGENTS.md是一个简单、开放的标准…...
避开这些坑!大模型评测中90%人会犯的3个方法论错误
避开这些坑!大模型评测中90%人会犯的3个方法论错误 当你在GitHub上看到一个最新开源大模型的评测结果排名第一,是否立刻想把它集成到自己的产品中?别急——你可能正踩进大模型评测最常见的认知陷阱。去年我们团队在客户服务场景中测试了7个榜…...
7个关键指标!Walrus存储节点监控完整指南:确保去中心化存储高可用性
7个关键指标!Walrus存储节点监控完整指南:确保去中心化存储高可用性 【免费下载链接】walrus-docs Original repository holding documentation and examples for the Walrus decentralized storage system. 项目地址: https://gitcode.com/GitHub_Tre…...
单细胞测序质控分析(QC)实战指南:从数据加载到低质量细胞识别
1. 单细胞测序质控分析的重要性 第一次接触单细胞测序数据时,我被那些密密麻麻的数字表格搞得头晕眼花。直到导师指着某个样本说"这个细胞已经死了",我才恍然大悟——原来原始数据里藏着这么多"坑"。单细胞测序就像给每个细胞拍X光片…...
