C++ 服务器 五 TCP详解二

23 篇文章 0 订阅
13 篇文章 3 订阅

  今天我们继续介绍C++服务器的第五部分。

   我们继续讲TCP是如何来保证他的传输的可靠的,有链接的呢?为了做到这些呢工程师们实际上是吧每台机器的TCP做成了一个状态,那么TCP有哪些状态?

  

这里我们简单列举了一些TCP的状态。

 首先最开始的,比如机器刚启动我们要和另一台机器创建TCP链接,那么他最开始的状态就是我们最下边的状态CLOSED,实际上他是一个不存在的状态,他是什么都没有,是我们假象的一个状态。

  LISTEN是监听状态,一般是发生在服务器的TCP端,服务器一般会打开一个端口,等待客户端来进行链接。

 SYN-SENT在我们TCP头部的时候就有这个SYN

这个状态是当你的客户端向服务器发送第一个包之后他的状态就会从我们上边所说的CLOSED状态变成了一个SYN-SENT状态,这种状态常常在客户端中出现。

那下边的SYN-RECESIVE自然就是一个服务器的状态,当客户端发送的第一个包被服务器接受之后,服务器就会变成SYN-RECESIVE状态。

 当客户端发送数据包,服务器接受数据包,两个之间的通讯链接起来之后两边的状态就会变成ESTABLISHED状态表示两边的数据正式建立起来了,里边的S代表着SERVER服务器C代表CLIENT我们的客户端。

 等客户端和服务器关闭的时候也就是需要断开连接,这时候状态会进入FIN-WAIT-1以及FIN-WAIT-2,之后我们会对这些状态进行更加详细的解释。包括下边的一些状态。

  大体来分TCP可以分为三种大部分的状态先是我们在建立连接之前的状态,之后就是建立好连接之后的正常状态,剩下的就是我们的关闭的状态。TCP主要有十个状态加上一个最后的虚拟的状态。

 

这是TCP的一个状态转换图看起来还是比较复杂的。

这里办蓝色的线一般来说是我们服务器的变化过程。图中的棕色的线一般是我们客户端的状态变化曲线,有一些特殊异常情况下会出现黑虚线的状态变化。

 我们先讲解一下服务器是如何变化的。首先初始状态是我们的虚拟状态也就是CLOSED状态,当程序启动的时候,他会监听端口,比如我们监听的是80端口,这时候服务器就会被动的将状态转换成LISTEN状态,这就好像我们现在开店,我们将我们门口的牌从非营业变成了开始营业,就是我们从CLOSED状态变换成LISTEN的过程,开始等待顾客的到来。假如这时候客户端发送来了数据,服务器会收到SYN的数据包,服务器收到后就会返回SYN和ACK的包给客户端。来告诉客户端我收到了你的数据,ACK之前我们也介绍过就是acknowledge1的缩写就是确认。当这时候服务器就会转换自己的状态变成上边所说的SYN-RECESIVE状态,之后服务器和客户端达成链接,状态就会变成ESTABLISHED,当服务器准备关闭的时候,他会给客户端发送一个FIN,然后会收到一个客户端给他的ACK代表客户端明白服务器要进行关闭了。然后服务器就会进入CLOSE WAIT状态,再进入LAST ACK状态,之后服务器就关闭了。这里我们所说的关掉是说建立的链接进行关闭了,并不是说整个服务器关机了断电了。我们看左右两个蓝色的框中右边蓝色框的右上角有两个英文单词passive close意思是被动的关闭,一般来说我们的服务器很少主动关闭通讯情况。原因我们会在下边进行讲解。

  我们继续讲解客户端的状态转换情况,一样客户端启动之前状态保持在CLOSED状态,之后开始主动向服务器端发送链接,之后他会收到一个SYN,因为服务器在监听之后会返回一个SYN,再往后状态就会变成SYN-SENT状态,之后客户端发送SYN和ACK,客户端和服务器就会都变成ESTABLISHED状态。当客户端想要关闭通讯的时候,就会进入左边的篮框也就是ACTIVE CLOSE主动关闭的状态。就会从ESTABLISHED变成FIN-WAIT-1,然后会继续发送ACK确认,再进入FIN-WAIT-2的状态,再次发送ACK,就进入了TIME-WAIT状态,上边也有解释,用来确认对方已经收到你想要关闭的消息,虽然服务器和客户端都可以使用,但是我们的服务器要少用慎用,为什么呢?这个问题的答案就是为什么我们很少让服务器主动关闭通讯的原因。是因为我们客户端和服务器进行通讯链接的时候当进入TIME-WAIT状态的时候,接受到的服务器+端口号是不能继续进行使用的。除非经过了下边TIMEOUT的时间段,这个TIMEOUT时间段一般有30s,但是这个都是可以手动去设置的。也就是说这么长一段时间内,是不能进行反应的,对于客户端来说这种是可以接受的,但是对于服务器来说,如果有一千个链接过来,如果这些都由服务器来进行CLOSE,那无形中就会浪费掉一些服务器中的一些资源。这段的理解我也不是很深刻,如果以后对这个问题有更好的理解的话,会再给大家去解释一下。

  接下来,我们具体讲解一下服务器和客户端之间到底是如何建立连接的。对于建立连接我们常常会说三次握手,也就是说服务器和客户端之间会发生三次交互。

图中的斜线就是服务器和客户端之间的交互一次握手。首先是服务器端必须在LISTEN状态下,然后客户端需要知道服务器的IP地址和IP然后CLIENT调用了connect()之后客户端就进入了SYN-SENT状态并且同时发送了SYN M,当这条消息进入SERVER端的时候,SERVER端会进入SYN-RECV状态,代表服务器端已收到消息,这时候服务器端会SYN N意味着服务器将自己的TCP中的SYN变成了1同时确认ACK状态也变成1。这时候上边调用的connect函数返回了过来,这时候客户端变成了ESTABLISHED状态意味着我当前已经可以对服务器发送消息了,这时在操作系统的底层会再发送数据给服务器,也就是服务器刚刚发送给客户端数据的一种返回,这时候收到的数据给服务器之后实际上是对服务器accept函数的一种返回。

 通俗的来说服务器开始的时候调用accept函数,函数中调用了了客户端的connect函数,然后客户端中开始执行connect函数在这个函数中会再次给服务器发送数据,然后服务器接收后会返回给客户端一个数据,收到这个数据的时候connect函数就算是有了返回值,这个函数就调用结束了。此时调用connect的accept函数还没有结束,并且这时系统会再给服务器一个数据,当服务器收到这个数据的时候他自己调用的accept函数就会结束。这时候两边都进入了ESTABLISHED状态。

  看这个图可以看出来,当我们服务器端的accep函数进行返回的时候这时候三次握手已经结束了,服务器和客户端之间的链接已经被建立了起来,比如说现在我们需要完成一个应用程序,我们需要屏蔽某些地区的ip地址链接进来,如果用我们所写的服务器来做,实现起来是有问题的,但是当我们获取到对象的ip并且要进行处理的时候这时候的链接是已经建立起来的,无非是说当我们accept函数返回之后,我们来进行判定,我们现在的ip是不是需要进行屏蔽的是,如果是那我们就需要让服务器去主动断开链接,进入我们上边所说的timeout。这样效率就有那么一点点的不高。

  今天对服务器的介绍先到这里,因为我自身并没有任何基础,也是一个小白,所以很多地方介绍的还是并不深刻和详细。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值