TCP是什么

网络游戏

网络游戏类型

  • 对等的客户端与服务端

    • 周期短
    • 游戏核心逻辑算法独立于玩家客户端上运行
    • 基于局域网
对等的客户端和服务端
  • 基于大厅的网络游戏

    • 大厅仅负责把不同的客户端撮合到一起
    • 在与大厅相连的游戏数据库中存放玩家账户信心以及积分信息
    • 每个玩家即可充当服务端也可充当客户端
基于大厅的网络游戏
  • 纯C/S结构的网络游戏

网络协议

TCP/IP起源于美国国防部
OSI模型
IP模型
数据进入协议栈的封装

IP网际协议

TCP是以太网协议和IP协议的上层协议,也是应用协议的下层协议。最底层的以太网协议(Ethernet)规定了电子信号如何组成数据包(packet),解决子网内网点对点通信。但是,以太网不能解决多个局域网之间的互通,这个就由IP来解决了。

IP(Internet Protocol Suite,网际协议簇)可连接多个局域网,IP定义了一套自己的地址规则,称为IP地址。IP实现了路由功能,允许局域网主机之间发送消息。路由器就是基于IP协议的,局域网互通要靠路由器连接。

路由的原理很简单,市场上所有的路由器,背后都有很多网口,要接入多根网线。路由器内部有一张路由表,规定A段IP地址走出口1,B段地址走出口2....,通过这套“指路牌",实现数据包的转发。

路由

IP特点

  • 不可靠 unreliable
  • 无连接 connectionless

IP数据报格式首部字段

  • BigEndian
    网络数据都是按照BigEndian来传输的


    BigEndian
/**
 * 32位4字节的整数值1在计算机编码表示为十六进制 0X 00 00 00 01
 * 大端系统内存中的表示为 01 00 00 00 BigEndian
 * 小端系统内存中的表示为 00 00 00 01 LittleEndian
 * */
union EndianTest
{
    int8_t u[4];
    int32_t i;
}
static bool isLittleEndianSystem()
{
    EndianTest et;
    et.i = 1;
    return et.u[0] == 1;
}

TCP

IP协议只是一个地址协议,并不保证数据包的完整。如果路由器丢包,比如缓存满了,新进来的数据包就会丢失。此时就需要发现丢了哪个包,以及如何重新发送这个包。这时候就要依靠TCP协议。

简单来说,TCP协议的作用就是保证数据通信的完整性和可靠性,防止丢包。

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接、可靠的、基于字节流的传输层通信协议,由RFC 793定义。

由于IP的特点是无连接不可靠,TCP是如何利用IP的呢?

  • TCP将应用程序的传输数据分割为合适的数据块(报文段)
  • 定时器timer
  • 延迟确认
  • 校验和
  • 流量控制
TCP与IP

以太网数据包

  • 以太网数据包(packet)的大小是固定的,最初是1518bytes,后增加到1522bytes。其中1500bytes是负载(payload),22bytes是头信息(head)。
Ethernet packet 1522bytes = 22bytes + 1500bytes
  • IP数据包在以太网数据包的负载里面,有自己的头信息,最少20bytes,所以IP数据包的负载最多为1500 - 20 = 1480bytes。
IP packet 1500bytes = 20bytes + 1480bytes
  • TCP数据包在IP数据包的负载(payload)里面,其头信息(head)最少也需20bytes,因此TCP数据包的最大负载是1480-20=1460bytes。由于IP和TCP协议往往有额外的头信息,所以TCP负载实际为1400bytes左右。
TCP packet 1480bytes = 20bytes + 1460bytes
数据包
IP数据包在以太网数据包里面,TCP数据包在IP数据包里面

因此,一条1500bytes的信息需要2个TCP数据包。HTTP/2协议的一大改进就是压缩HTTP协议的头信息,使得HTTP请求可放在TCP数据包中,而不是分成多个,这样也就提高了速度。

一个包1460bytes,一次性发送大量数据,就必须分成多个包。比如,一个10MB文件,需要发送 10 * 1024 * 1024 / 1460 = 7182 个包。

TCP报文段的编号

发送时TCP为每个包编号(sequence number,简称SEQ)以便接收方按照顺序还原,万一发生丢包,也可以知道丢失的是那个包。

第一个包的编号是一个随机数,每个数据包包含两个编号,自身编号以及下一个包的编号。接收方由此得知,应按照何种顺序将它们还原为原始文件。

数据包的编号

接收方收到TCP数据包以后,组装还原是操作系统完成的,应用程序不会直接处理TCP数据包。

对于应用程序来所,不关心数据通信的细节。除非线路异常,收到的总是完整的数据。

应用程序需要的数据放在TCP数据包里面,均有自己的格式,例如HTTP协议。

TCP并没有提供任何机制,表示原始文件的大小,这由应用层的协议来规定。比如HTTP就有一个头信息Content-Length,表示信息体的大小。对于操作系统而言,就是持续地接收TCP数据包,将它们按顺序组装太,并且一个包都不能少。

操作系统不会去处理TCP数据包里面的数据,一旦组装好TCP数据包,就将其转交给应用程序。TCP数据包里面有一个端口port参数,就是用来指定转交给监听该端口的应用程序。

TCP 报文段首部

  • TCP传送的数据单位协议是TCP报文段(segment)
  • TCP是面向连接的传输层协议,每条TCP连接只能有2个端点(endpoint),每条TCP连接只能是点对点的(一对一)。
  • TCP提供可靠交付的服务
  • TCP提供全双工通信并面向字节流
TCP
  • 源端口号 SourcePort
    16位2字节,源端口号和源主机IP地址共同标识主机的应用进程

  • 目标端口DestinationPort
    16位2字节,目标端口号和目标主机IP地址共同标识目标主机的应用进程
    端口是传输层与应用层的服务接口,传输层的复用和分用功能都要通过端口才能实现。
    表示数据从哪个进程来到哪个进程去

  • 序列号Sequence Number
    32位序号,用于对发送的字节流进行计数,表示发送端报文段中第一个数据字节的顺序号。
    占4bytes,TCP连接中传送的数据流中的每个字节都编上一个序号,序号字段的值则指的是报文段所发送的数据的第一个字节的序号。

  • TCP报头长度
    4位首部长度,数据偏移/首部长度,指出TCP报文段的数据起始距离,即TCP报文段的起始处有多远。数据偏移的单位是32bit = 4bytes。

  • 保留位
    占6位,保留为今后使用,目前为0。

  • 控制位
    6位标志

URG 
标识紧急指针是否有效
当`URG=1`时表明紧急指针字段有效,告诉系统此报文段中有紧急数据,因尽快传送,相当于优先级。

ACK 
标识确认序号是否有效
`ACK=1`时确认号字段才有效,当`ACK=0`时确认号无效。

PSH 
提示接收端应用程序立即将数据从TCP缓冲区读走
接收TCP收到`PSH=1`的报文段,就尽快地交付接收应用进程,而不再等到整个缓存都填满了再向上交付。

RST 
要求重新建立连接,把含有RST标识的报文称为复位报文符。
`RST=1`时表明TCP连接中出现严重差错,例如由于主机崩溃或其他原因,必须释放连接然后再重新建立运输连接。

SYN 
请求建立连接,把含有SYN标识的报文称为同步报文段。
同步`SYN=1`时表示一个连接请求或连接接收报文

FIN 
通知对端,本端即将关闭,把含有FIN标识的报文称为结束报文符。
用来释放一个连接,`FIN=1`表明此报文段发送端的数据已发送完毕,并要求释放运输连接。
  • 确认号
    占4bytes,是期望收到对方的下一个报文段的数据的第一个字节的序号。
  • 校验和
    占2bytes,校验和字段校验的范围包括首部和数据两部分,在计算检验和时要在TCP报文段前加上12bytes的伪首部。

  • 紧急指针
    占16位,指出本报文段中紧急数据共有多少个字节,紧急数据放在本报文段数据的最前面。

  • 选项
    长度可变,TCP最初只规定了一种选项,即最大报文段长度MSS(Maximum Segment Size),MSS告诉对方TCP”我的缓存所能接收的报文段的数据字段的最大长度是MSS个字节“,MSS是TCP报文段中的数据字段的最大长度,数据字段加上TCP首部才等于整个TCP报文段。

  • 填充
    为了使整个首部长度是4bytes的整数倍

  • 窗口扩大
    占3bytes,其中有一个字节表示移位值S,新窗口值等于TCP首部的窗口位数增大到16+S,相当于把窗口值向左移动S位后获得实际的窗口大小。

  • 时间戳
    占10bytes,最主要的字段时间戳字段4bytes和时间戳会送回答字段4bytes

  • 选择确认
    接收方收到和前面字节流不连续的2bytes,如果这些字节的序号都在接收窗口之内,那么接收方就先收下这些数据,但是要把这些信息准确地告诉发送方,使发送方不要再重复发送这些已收到的数据。

TCP状态

  • LISTEN(S)
    服务器等待客户端前来连接
  • SYN-SEND(C)
    客户端尝试连接服务器
  • SYN-RECEIVED(S)
    服务器确认首次连接
  • ESTABLISHED(SC)
    服务器和客户端建立连接,双方可以发送数据,为常态。
  • FIN-WAIT-1(SC)
    等待对方关闭
  • FIN-WAIT-2(SC)
    等待对方关闭
  • CLOSE-WAIT(SC)
    等待自己应用程序关闭
  • CLOSING(SC)
    等待对方确认确认自己的关闭
  • LAST-ACK(SC)
    等待最后一次确认消息
  • TIME-WAIT(SC)
    确认对方收到自己的关闭消息,服务器慎用。
  • CLOSED(SC)
    实际是一个不存在的状态
TCP状态转换
TCP状态变迁
服务器TCP所经历的典型的TCP状态序列

TCP通信

TCP通信过程包括三个步骤

  • 建立TCP连接通道(三次握手)
  • 数据传输
  • 断开TCP连接通道(四次握手)
TCP通信过程

TCP建立连接

所谓三次握手(Three-Way Handshake)就是建立TCP连接,就是说建立一个TCP连接时,需要客户端和服务器总共发送3个包以确认连接的建立。在socket变成中,此过程由客户端执行connect来触发。

TCP建立连接为什么要进行三次握手(Three-Way Handshake)呢?

为了防止已失效的连接请求报文段突然又传送到服务端所产生错误

当客户端发出第一个连接请求报文段并没有丢失,而是在某个网络节点长时间的滞留,以至于延误到连接释放以后的某个时间点才到达服务器。

本来这是一个早已失效的报文段,但服务端收到此失效的连接请求报文段后,误以为是客户端再次发出的一个新的连接请求。于是向客户端发出确认报文段,同意建立连接。

假设不采用三次握手,那么只要服务器发出确认,新的连接就建立了。由于现在客户端并没有发出建立连接的请求,因此不会理睬服务器的确认,也不会像服务器发送数据。但是服务器却以为新的运输连接已经建立,并一直等待客户端发来请求。这样,服务器的很多资源就会白白浪费掉了,采用三次握手可防止上述情况。

三次握手

三次握手
  • 第1次握手
    1. 客户端将同步标志位SYN置为1 SYN=1
    2. 客户端随机产生一个序列号seq=J,将该数据包发送给服务器。
    3. 客户端进行SYN_SEND状态,等待服务器确认信息。
  • 第2次握手
    1. 服务器收到数据包后,由同步标志位SYN=1得知客户端请求建立连接。
    2. 服务器将同步标志位SYN和确认标志位ACK置为1 SYN=1 ack=J+1,并随机产生一个序列号seq = K,然后将该数据包发送给客户端以确认连接请求。
    3. 服务器进入SYN_RCVD状态
  • 第3次握手
    1. 客户端收到确认后检查ack是否为J+1,ACK是否为1。如果正确则将确认标志位ACK置为1 ack=K+1,并将该数据包发送给服务器。
    2. 服务器检查ack是否为K+1并检查ACK是否为1,若正确则连接建立成功。
    3. 客户端和服务器进入ESTABLISHED状态,完成三次握手。随后客户端和服务器之间可以开始传输数据了。

简单来说,就是

  1. 建立连接时,客户端发送SYN包SYN=1到服务器,并进入SYN-SEND状态,等待服务器确认。
  2. 服务器收到SYN包,必须确认客户端的SYNack=i+1后,发送一个SYN包SYN=k即SYN+ACK包,此时服务端进入SYN-RECV状态。
  3. 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACKack=k+1,此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,然后开发相互传送数据。
TCP连接确认

SNY攻击

在三次握手过程中,服务器发送SYN-ACK之后,收到客户端ACK之前的TCP连接称为半连接(half-open connect),此时服务器处理SYN-REVD状态。当收到ACK后,服务器转入ESTABLISHED状态。

SYN攻击就是客户端在短时间内伪造大量不存在的IP地址,并向服务器不断地发送SYN包,服务器回复确认包,并等待客户端确认,由于源地址不存在。因此服务器需要不断重发直至超时,这些伪造的SYN包将产生时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当服务器上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了。

// 检测是否遭到SYN攻击
$ netstat -nap | grep SYN_RECV

四次挥手

所谓四次挥手(Four-Way Wavehand)即终止TCP连接,也就是断开一个TCP连接时,需要客户端和服务端发送4个包以确认连接断开。在socket编程中,此过程是由客户端或服务端任意一方执行close来触发。

四次挥手
  • 第1次挥手
    客户端发送一个FIN用来关闭客户端到服务器的数据传送,客户端进入FIN_WAIT_1状态。
  • 第2次挥手
    服务器收到FIN后发送一个ACK给客户端,确认序列号为收到序号+1,与SYN相同一个FIN占用一个序列。服务器进入CLOSE_WAIT状态。
  • 第3次挥手
    服务器发送一个FIN用来关闭服务器到客户端的数据传送,服务器进入LAST_ACK状态。
  • 第4次挥手
    客户端收到FIN后进入TIME_WAIT状态,然后发送一个ACK给服务器,确认序号为收到序号+1,服务器进入CLOSED状态完成四次挥手。

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭,即发送方和接收方都需要FIN和ACK。这个原则是当一方完成它的数据发送任务后发送一个FIN来终止这个方向的连接,收到一个FIN只是意味着这一方向上没有数据流动。一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

TCP通信过程

为什么建立连接是三次握手而关闭连接却是四次挥手呢?

因为服务器在LISTEN状态下,收到简历连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,但收到对方的FIN报文时,仅仅表示对方不再发送数据了,但是还能接收数据。己方也未必全部数据都发送给对方了,所以己方可以理解关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此己方ACK和FIN一般都会分开发送。

四次挥手

为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回CLOSE状态?

  • 保证TCP协议的全双工连接能够可靠关闭
    如果客户直接关闭,那么由于IP协议的不可靠性或其他网络原因,导致服务器没有收到客户端最后回复的ACK,那么服务器会在超时之后继续发送FIN,此时由于客户端已经关闭了,就找不到与重发的FIN对应的连接,最后服务器会受到RST而不是ACK。服务器会以为是连接错误,然后把问题报告给高层,这样的情况虽然不会造成数据丢失,但是却导致TCP不符合可靠连接的要求。所以,客户端不是直接进入CLOSED,而是要保持TIME_WAIT,但再次收到FIN时能够保证双方收到ACK,最后正确的关闭连接。

  • 保证此次连接的重复数据段从网络中消失
    如果客户端直接CLOSED,然后又再次向服务器发起一个新连接,不能保证这个新连接与刚关闭的连接的端口号是不同的,也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是存在特殊情况的出现。假设新连接和已经关闭的老连接的端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才能到达服务器,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair。于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍的MSL,这样保证本次的所有连接都从网络中消失。


    2MSL

TCP数据相互双送

  • 交互式与成块的数据两种
  • 时间延迟确认
  • Nagle算法(游戏开发一般关闭这个算法)
  • 接收窗口大小

Socket编程

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280