- 博客(160)
- 收藏
- 关注
原创 【计算机网络】 基于TCP的简单通讯(客户端)
连接服务端我们使用的是connect()函数,分别为连接使用的socket,连接的地址信息,连接的地址信息长度。返回值为int类型,如果没有错误返回0,否则返回SOCKET_ERROR。这样我们的TCP协议简单通讯就写好了。没有什么问题,可以一人说一句话。先运行服务端再运行客户端。
2023-09-28 23:30:18
319
原创 【计算机网络】 基于TCP的简单通讯(服务端)
接收数据我们使用recv()函数,这个函数相比recvfrom()少了两个参数,它不需要记录对端的地址信息了,因为已经跟对端连接成功了,已经知道对端的地址信息了,连接成功返回的socket就像是连接在两端的一条绳。监听我们用listen()函数进行,他有两个参数,第一个为socket,意为派哪个socket去进行监听,第二个参数为int值,它是能够等待被连接的队列的最大长度,返回值如果是0就没有问题,为SOCKET_ERROR就报错。发送数据我们使用send()函数,原理和recv()函数相同。
2023-09-27 23:51:52
117
原创 【计算机网络】 基于UDP的简单通讯(客户端)
不需要绑定ip地址是因为绑定ip地址是在操作系统那里注册,那么为什么客户端不需要绑定而服务端就要绑定呢,原因是有发送数据的顺序决定的,一般都是客户端先发,主动发消息的时候操作系统就会自动给分配一个端口号,然后操作系统也会帮助选择一个网卡。客户端跟服务端差不多,也要先加载库,在加载库之后也要创建套接字,但是客户端一定是没有绑定ip地址的,之后是循环发送数据和接收数据,最后关闭套接字、卸载库。因为我们已知对端的ip,所以在接收数据的时候不需要使用输出参数,填NULL即可。运行一下,先开启服务端再开启客户端。
2023-09-26 23:31:54
149
原创 【计算机网络】基于UDP的简单通讯(服务端)
第一个变量是ip地址类型,我们用的ipv4类型,第二个是端口号,第三个是ip地址。函数的参数有六个,第一个为socket,意为使用哪个socket进行接收,第二个参数为char*,是一个输出参数,是用来接收数据的缓冲区,第三个参数为这个缓冲区的大小,第四个参数是一个标志位,用来决定当前的接收方式,我们在这里不做特殊设置,用默认的即可,下一个参数也是一个sockaddr *输出类型的参数,用来存放数据是从哪里来的,最后一个参数当然就是上一个参数的长度,但由于它属于是输出类型的参数,所以要变为指针类型。
2023-09-25 23:52:07
176
原创 【计算机网络】 拥塞控制
网络中的链路容量和交换节点中的缓存和处理机都有着工作的极限,当网络的需求超过他们的工作极限时,就出现了拥塞。在网络中出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这是TCP就会重传数据,但是 一重传就会导致网络的负担更重,于是会 导致更大的时延以及更多的丢包,这个情况就会进入恶性循环被不断地放大…当收到三个重复的ACK时,触发快重传机制,那么cwnd会变为原来的一半,然后ssthresh等于当前的cwnd,然后使用快恢复的算法,cwnd=ssthresh+3,然后继续使用拥塞避免算法。
2023-09-20 20:23:57
427
原创 【计算机网络】 Nagle算法
Nagle算法默认是打开的,如果对于一些需要小数据包交互的场景的程序,比如telnet或ssh这样的交互性比较强的程序,则需要关闭Nagle算法。Nagle算法就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。(因为在传输时不会因为数据包小而传输的快,是根据包的个数转发的)
2023-09-19 21:03:23
346
原创 【计算机网络】 心跳机制
就是每隔几分钟发送一个固定信息给服务端,服务端收到后回复一固定信息。如果服务端几分钟内没有收到客户端信息则视客户端断开。
2023-09-18 18:04:23
336
原创 【计算机网络】 粘包问题
tcp是数据流传输,是一种没有边界的,可以合并的传输数据方式。合并就要能拆开,拆不开就是粘包。适用场景:适合用户可输入的内容比较有限比较固定的情况。缺点:数据可能和标志位重合,导致错误拆包。适用场景:适合每次发的大小基本是固定的。缺点:每次会多发一个包,浪费空间。设置标志位(起始/结束标志位)先发数据长度,然后再发数据包。缺点:容易浪费空间和资源。适用场景:适合网页浏览。缺点:浪费时间和资源。
2023-09-15 20:50:04
398
原创 【计算机网络】 TCP流量控制——滑动窗口和累积应答
我们前面所说的是我们每发送一个包对端就要回一个ack,那么这样效率太慢了,我们这里就有一个累积应答的机制,就是说我们客户端累积发送多个包,然后服务端再统一进行回复。那么我们累积应答时具体发送多少数据之后统一回复一个ack是由什么决定的呢,就是由我们之前所说的窗口的大小来决定的。主要的方式就是返回的ACK中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。当发送数据过程中有一个或多个包丢失,从序号小的位置回复一个ack,让发送端重新发送。
2023-09-13 23:34:00
258
原创 【计算机网络】 RTT和RTO
路由器排队是因为他不止给一个人处理数据,他会给所有经过它的数据进行处理,当这个路由器收到的数据比较多,它每秒能够处理的数据量是有限的,那么多出来的数据就要等到下一秒才能够处理,然后等待处理的数据的队列可能越排越长,在排队的过程中就有可能出现超时了,所以往返时延是一个重要的指标。RTT(Round-Trip Time)是计算机网络中的一个重要的性能指标,表示从发送端发送数据开始,到发送端接收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。也就是从发送数据到接收到ack的时延。
2023-09-12 20:51:35
322
原创 【计算机网络】 TCP——四次挥手
答:因为最后等待2MSL是为了防止最后一次ACK丢失,如果ACK丢失了,在2MSL中会再次收到FIN,那就再回一个ACK,如果没有再次收到FIN,就证明ACK没有丢失,就可以放心进入CLOSE状态了,如果不等待就关闭并且ACK包丢失了,那么被动方就会一直重复发FIN包。答:要将之前收到的数据都处理完再回复FIN包,立刻回ACK是为了防止超时重传,因为如果处理数据的时间过长就会触发超时重传机制。
2023-09-11 22:55:02
858
原创 【计算机网络】TCP传输控制协议——三次握手
答:因为当接收到的包中不止有ack,那么需要回复一个ack,否则会产生超时重传,服务端需要接收到发送ACK的ACK才能建立连接。答:因为服务端在发送ACK包的同时也可以发送SYN包,原因是这两个标志位在逻辑上不产生冲突。
2023-09-10 14:46:32
726
原创 【计算机网络】 确认应答机制与超时重传
那如果是服务端回复的ack丢失,道理也基本相同,也是在规定时间内没有收到服务端回复的ack包,那么就再次发送一遍数据,不同的是因为服务端已经接收到过这个数据了,所以不会再次处理这个数据,就把重复的包丢弃,然后重新回复一遍ack。在我们客户端发送数据的同时会有一个定时器,如果在规定时间没有收到服务端回复的ack,那么就证明我们的包丢失,那就再给服务端重新发送以下丢失的包。200,服务端收到后再回一个ack=201,在书写过程中,我们一定要先把标志位置1,然后再发送数据包,否则包是失效的。
2023-09-09 14:42:11
880
原创 【计算机网络】 TCP协议头相关知识点
首先是源端口和目的端口,这两个是UDP中也有的,但是UDP中只有这两个,没有后面的校验数据,接着是序号(seq)和确认号(ack),他们两个是配合使用的,比如说发送端发送了一个序号为1的seq,然后接收端回一确认号为2的ack,就证明说收到了seq为1的这个包,可以继续发送seq等于2的包,这样可以保证数据可靠,序号还能保证顺序不乱。最后可变部分的原理和IP部分也基本一样。在开发过程中,我们要坚持一个不信任原则,不管是在哪一层,干什么都要对数据进行校验,因为在任何时候我们的数据都有可能被他人访爆。
2023-09-08 20:49:52
717
原创 【计算机网络】 IP协议格式以及以太网帧结构
生存时间是一个倒计时,当计时为0时,这个包的生存时间就到了,当某一个路由器在转发时发现你的生存时间为0时就会将这个包丢弃,原因是有的包会在传输过程中迷路,那么这种数据包不能让它在网络中一直存在,这就造成了丢包,他会占用我们的带宽,生存时间不是单纯的时间,而是能经过路由器的个数。可变部分就是为了我们想要在ip层网络层加一些东西,因为收到数据时是先到达网络层,然后到达传输层应用层的,所以网络层一定会先处理数据,比如用华为的手机连接华为的路由器,是不需要密码的,那么就是在网络层处理的。
2023-09-07 19:11:34
576
原创 【计算机网络】 子网划分
我们知道C类ip默认子网掩码位255.255.255.0,C类ip的网络号应该是24位,故其借用了主机位4位来充当网络位,所以创建的子网个数就是2 ^ 4 = 16。从0开始不断增加,直到到达子网掩码值,中间的结果就是子网,即0,64,128,192。网关都是具有路由功能的ip地址,就是说网关必须要有路由功能,默认的主机号都是0,这样的才是网关。具有正常的网络号部分,而主机号部分全为1的ip地址称之为广播地址。非默认的子网掩码中1的个数一定比默认子网的多,并且1要连续,这些1是从原来的主机号中借来的。
2023-09-06 10:04:56
918
原创 【计算机网络】 ARP协议和DNS协议
ARP协议实现的过程就是自己设备会发送一个ARP Request的广播,那么当前路由器所连接的所有设备都会收到这个广播,数据包中的目的MAC填0,所有收到这个广播的设别都会看自己的IP是不是这个广播的目IP,如果不是就会将这个包丢弃,如果是就会回一个ARP Reply的单播,然后就可以开始通信了。当发送端广播ARP请求时,本地网络上不会有主机回应(因为IP地址是外网的),此时路由器将会回应该请求,则发送源认为路由器就是目的主机,会将报文全部转发给它,再由路由器转发报文到外网,则该路由器就被称为ARP代理。
2023-09-05 19:10:19
792
原创 【计算机网络】 七层网络模型
是支持TCP/IP协议的网络通信的基本操作单元,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。比如我们如果在登录一个网站之后,浏览页面过程中要跳转网页,那么不需要重复登录,靠的就是session会话管理,他就是保证在同一个网站中不管多少次的页面跳转,都不需要重新登录。传输层通信协议,有流量控制和差错控制,使用TCP协议的应用比如邮件的接收和发送、文件传输、远端登录。想要使数据发送的快,就要对数据进行压缩,也会使网络更通畅。
2023-09-05 14:22:06
99
原创 【计算机网络】 静态库与动态库
把头文件拷贝到当前项目中,添加头文件依赖把库文件拷贝到当前项目中,添加库文件依赖把头文件拷贝到当前项目中,添加头文件依赖把索引文件拷贝到当前项目中,添加索引文件依赖把dll拷贝到exe同文件下。
2023-09-04 19:32:29
1108
原创 【C++】 Qt-线程并发与线程同步
我们再创建一个控制台文件命名为main2.cpp,然后在这个文件中创建三条线程,在这三条中同时为一个全局变量进行递增操作,并在最后输出这个全局变量。在Qt中封装了创建线程的类:QThread,一般情况下,手动添加一个类继承QThread,这样既能继承QThread的功能,又能扩展自己的功能。我们创建一个带有设计界面的项目,并且在设计界面中放入一个进度条以及四个按钮组件,组件的作用分别是启动、暂停、恢复和退出。报错原因是:在另一个线程中设置了当前组件的值时,使用sendEvent发送事件,跨线程报错。
2023-07-15 20:52:37
526
1
原创 【C++】 Qt-线程挂起、恢复和退出
操作系统内核知道当前有多少进程正在使用某个内核对象,内核对象被创建时,其使用计数为1,另一个进程访问该内核对象后,使用计数加1,当进程终止时,使用计数减1,手动关闭内核对象时,使用计数再减1,最终使用计数为 0时,操作系统将销毁该内核对象。内核是操作系统提供底层服务的一个模块,而内核对象则是内核分配的一个内存块,它是一种数据结构,不同的内核对象具有不同的结构,负责维护对象相关的信息 ,少数成员如:安全描述符、使用计数等是所有内核对象都有的,其他多数都是不同的。保证所有子线程都退出后,主线程再退出。
2023-07-12 11:38:16
452
原创 【C++】 Qt-线程进程
应用程序和进程间的关系:从任务管理器的详细信息页面可以看出,一个应用程序可以启动多个进程,PID(part ID)是进程唯一标识符,就像人的身份证号。后来,随着计算机的发展,对CPU的要求越来越高,进程之间的切换开销较大,已经无法满足越来越复杂的程序的要求了,于是就发明了线程。进程概念:是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立的基本单元,是应用程序运行的载体。通过测试我们可以发现,我们是创建了一根新的线程,而不是简单的调用线程函数。
2023-07-08 07:23:09
482
原创 【C++】 Qt-事件(下)(事件过滤、自定义事件)
我们在界面上添加两个spin box用作计算的两个数,combo box作为计算的规则,push button将计算的结果以事件的形似发送出去。首先我们在主窗口的构造中添加好四种规则然后将计算按钮转到槽,然后在槽函数中获取数值//获取数值 int v1 = ui -> spinBox1 -> value();在之后我们去自定义一个类将继承父类修改为QEvent,构造函数参数改为事件的类型,添加事件携带的信息int m_v1;int m_v2;
2023-07-05 12:05:17
260
2
原创 【C++】 Qt-事件(上)(事件、重写事件、事件分发)
而对于事件,Qt使用一个**事件队列(windowSystemEventQueue)**对所有发出的事件进行维护,当新的事件产生时,会被追加到事件队列的尾部,前一个事件完成后,取出后面的事件进行处理。事件对象创建完毕后,Qt将这个事件传递给QObject::event()函数,event()函数主要用于事件的分发,一般情况下并不直接处理事件,而是将这些事件按照他们不同的类型,分发给不同的事件处理器(event handler)。一般我们重写某个组件的事件,需要自定义类,继承对应的组件类,重写感兴趣的事件。
2023-07-01 13:08:47
399
1
原创 【C++】 Qt-页面布局
label的text属性改为xx(&S),括号为英文,其中&用来指定快捷键,并不会显示到窗口上,指定的快捷键为0,当程序运行后,按下Alt+0即可将光标焦点切换到昵称的伙伴组件上。伙伴关系是指界面上的一个label和一个组件的关联,在程序运行时,在窗体上按快捷键快速将焦点切换到label的伙伴关系组件上。再获颁关系工具下,选中label标签拖动到后面的组件上,那么两者就成了伙伴关系,label的buddy属性,显示了关联的伙伴。【从这里开始】:代表从选中数字之后的顺序开始调整,之前的数字顺序为原来的顺序。
2023-06-29 13:44:19
734
1
原创 【C++】 Qt-信号与槽
在QMetaObject::connectSlotsByName(MainWindow);执行后,会自动匹配特定命名规则的槽函数,也就是说我们可以手动添加一个能被自动调用的槽函数。但这种方式并不是长久之计,如果我们手动指定信号与槽的绑定连接,需要用到函数QObject::connect。//方式一:*(常用推荐)const QObject *sender, //发出信号的对象const char *signal, //发送对象发出的具体信号。
2023-06-26 05:30:17
553
1
原创 【C++】 Qt-调试输出、字符串使用与简单提示对话框
QString的operator= 也并不支持std::string类型,但可以用其提供的静态函数QString::fromStdString(const std::string &str) 注意此函数并不直接作用于QString本身,而是通过返回值返回。QString的构造并不支持std::string类型初始化,需要将std::string转化为const char*,适用于初始化赋值。返回字串在原串中的位置下标,如果不存在子串,则返回-1,从字符串的头开始定位,如果存在多个,返回出现的第一个下标。
2023-06-25 13:08:17
902
原创 【C++】 Qt-认识Qt
Qt(官方发音[kju:t],同音cute)是一个跨平台的C++开发库,主要用来开发图形用户界面(Graphical User Interface,GUI)程序,当然也可以开发不带界面的命令行(Command User Interface,CUI)程序。同时也是图像用户界面应用程序框架,他为应用程序开发者提供建立艺术级图形界面所需的功能。它是完全面向对象的,很容易扩展,并且允许真正的组件编程。
2023-06-22 11:43:30
979
原创 【C++】 STL(下)算法、迭代器、容器适配器 和 仿函数
注意:因为尾节点没有实际意义,所以不能先取值再减减,可以在取值的同时加上一个左减减,这样每次输出的就是迭代器指向的前一个节点的值,同时也避免了取不到头节点的现象。特点:实现的是一个先入先出(First-In-First-Out,FIFO)的队列,它默认是用deque去实现的,但也可以用list等底层容器实现。仿函数的优势:它是有状态的函数,他也有类的特性,除了可以增加成员函数外还可以增加成员属性,就像上面的我们增加一个sum用来记录每次加的结果后累加。STL中的算法头文件位于和文件中(以为主)
2023-06-14 20:29:55
500
原创 【C++】 STL(上)STL简述、STL容器
STL体现了泛型编程的思想,大部分基本算法被抽象,被泛化,独立于与之对应的数据结构,用于以相同或近似的方式处理各种不同情形,为我们提供了一个可扩展的应用框架,高度体现了程序的可复用性。**剪切拷贝链表的某一段节点:**splice(iterator Where,list& Right,iterator First,iterator Last):将Right链表的First位置到Last位置的一段元素[First,Last),不包含Last,结合到this链表的Where位置之前,这是一个剪切操作。
2023-06-12 15:14:23
722
1
原创 【数据结构和算法】(练习题)判断数组中有无重复出现元素
给出一组数据,其中有n个元素,每个元素的数值范围在1~n-1之间,判断数据有无重复出现,若重复出现则报错。
2023-06-02 20:31:24
71
原创 【C++】 模板(泛型编程、函数模板、类模板)
假如这个函数的声明和定义是分开的情况下,那么这个模板该何去何从呢我们正常声明一个模板函数,然后在主函数下方去定义,然后调用fun9();return 0;我们会发现调试之后出现了这样一个错误:error C2783: “void fun9(void)”: 未能为“K”推导 模板 参数就是说我们的K没有指定,所以我们需要在函数的定义和调用的函数名后面都加上个
2023-05-24 12:31:13
708
原创 【C++】 设计模式(单例模式、工厂模式)
这两种方法各有各的优缺点,第二种方法的优点很明显,首先就是不需要考虑回收,而且不会有多线程下可能创建多个对象的问题第一种方法的优点在于因为他的对象是new出来的,所以支持在运行过程中随时去回收,而第二种方法只能等到程序退出时资源才会被系统回收对于简单工厂和工厂方法来说,两者的使用方式实际上是一样的,如果对于产品的分类和名称是确定的,数量是相对固定的,推荐使用简单工厂模式。抽象工厂用来解决相对复杂的问题,适用于一些列、大批量的对象生产。
2023-05-21 13:40:56
719
原创 【C++】 拷贝构造
我们在类中可以有无参构造,也可以有有参构造然后在定义对象的时候就可以直接定义或者带参的去定义但是我们发现,直接用对象等于一个值也可以带参的定义这里等号的左右边类型不同,左边是类对象,而右边是一个整型,所以我们判断这里发生了隐式的转换当参数有两个时(无默认值),我们无法发生转换构造,因为在赋值时不能直接赋两个值,只能通过括号去赋值不是只有一个参数才能发生转换构造,如果其他参数在构造函数中有默认值的话,那么也可以发生转换构造因为隐式类型转换可能会产生一些bug,所以我们尽量去避免隐式类型转换的发生。
2023-05-20 16:33:07
541
原创 【C++】 制作游戏壳
为了方便以后制作小游戏,我们将游戏中通用的方法以及属性抽离出来,制作成一个游戏壳,是制作游戏的效率更高!游戏壳包含两个文件:GameFrame.h main.cpp ,需要定义一个具体游戏类,继承游戏壳类(CGameFrame),重写四个虚函数 virtual void On_Init();//初始化 virtual void On_Paint();//重绘 virtual void On_Close();//关闭 virtual void AddMsgMap();
2023-05-18 12:57:41
469
原创 【计算机网络】第一章 计算机网络基础(期末急救包)
期末将至,相信有的同学们还在为怎么过期末而发愁吧!不用担心,即日起将会陆续更新期末特辑,保证在学完后可以顺利通过期末考试。本系列不止适用于期末考试,自考、考研的同学学习后也同样会有很大帮助。希望各位考的都会蒙的全对,期末顺利!
2023-05-12 20:21:20
521
原创 【C++】 类练习---封装链表、人物移动
在学完了【C++】 类基础汇总(类封装,构造、析构函数...)后,我们明白了类的特性以及使用方法,那么就需要用一些实例来巩固一下知识点,所以这篇文章就教你如何用类来封装链表和用类来写一个人物移动的小项目。int val;Node(int v) {//构造函数初始化val = v;以上就是两个用类来实现的小练习了,相信在学完之后你对类会有更深层次的理解,也能够明白类的重要性了。
2023-05-08 20:41:39
701
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人