TCP/IP、Http、Socket、XMPP-从入门到深入
终极iOS程序猿 2016-12-29 18:27
为了便于大家理解和记忆,我们先对这几个概念进行的介绍,然后分析他们的不同,再进行详细的分析。
一、TCP/IP简介
IP协议是网络层,TCP协议是传输层,HTTP协议是应用层,socket是对TCP/IP协议的代码封装和应用。
TPC/IP 主要解决数据如何在网络中传输,HTTP主要解决如何包装数据。
TCP/IP协议用来传输数据,应用层协议 使传输的数据有意义,应用层协议有很多,比如HTTP、FTP、TELNET等,也可以自己定义应用层协议。
比如:网页使用HTTP协议 封装HTTP文本信息,再用TCP/IP做传输层协议将它传送到浏览器。
二、Socket简介
Socket不是协议,而是一个可以调用的接口(API)。我们通过Socket,才能使用TCP/IP协议。
Socket跟TCP/IP协议没有必然的联系。Socket编程接口在设计的时候,就希望也能适应其他的网络协议。所以说,Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口,比如create、listen、connect、accept、send、read和write等等。
TCP/IP只是协议,必须要具体实现,还要提供对外的操作接口,这就是Socket编程接口。Socket本身不算是协议,就像上面所说,它只是提供了一个针对TCP或者UDP编程的接口。
三 、 TCP三次握手 简介
第一次握手:客户端发送包到服务器,等待服务器确认;
第二次握手:服务器收到并确认客户端的数据包,同时自己也发送一个数据吧回复给客户端;
第三次握手:客户端收到服务器的数据包,向服务器发送确认包,此包发送完毕,就完成了三次握手。
先来个形象的比喻:我(客户端)发了个邮件给你(服务端),(上面这是第一次握手),但是我不知道你收到没有,所以你发了个“我已经收到”的邮件回复给我(这是第二次握手)。我收到了你的邮件,但是你不知道 我到底有没有收到你的这封邮件,所以你不确定 我到底知不知道“你已经收到”。所以 我还要再发送个邮件 告知你 我收到邮件了(这是第三次握手)。。
这样就能确认彼此之间的通讯是正常的。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。
理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”。
四、Socket网络连接的步骤
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
1、服务器监听:服务器端 实时监控网络状态,处于等待连接的状态,等待客户端的连接请求。
2、客户端请求:客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。客户端的套接字必指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
3。连接确认:当服务器端套接字监听到客户端套接字的请求时,就建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续监听其他客户端的连接请求。
五、HTTP简介
HTTP(Hypertext Transfer Protocol ) 超文本传送协议,是建立在TCP协议之上的一种应用协议。
客户端发送的每次请求都需要服务器响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
六 . TCP和UDP的区别
TCP是面向链接的,虽然说网络的不安全不稳定特性决定了多少次握手都不能保证连接的可靠性,但TCP的三次握手在最低限度上,也很大程度上 保证了连接的可靠性;
而UDP传送数据前并不与对方建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收,当然也不用重发,UDP是无连接的、不可靠的一种数据传输协议。
所以UDP的开销更小数据传输速率更高,实时性更好。
所以采用TCP传输协议的MSN比采用UDP的QQ传输文件慢,但并不能说QQ的通信是不安全的,因为程序员可以手动对UDP的数据收发进行验证,比如发送方对每个数据包进行编号然后由接收方进行验证啊什么的。
七 . XMPP简介
XMPP(Extensible Messaging and Presence Protocol,前称Jabber)是一种以XML为基础的开放式即时通信协议,是经由互联网工程工作小组(IETF)通过的互联网标准。
XMPP网络是基于服务器的,即客户端之间彼此不直接交谈。
1、XMPP实际是怎么运行的,举个栗子:
Jabber识别符(JID)是用户登录时所使用的账号,通常像一个电子邮件地址,如[email protected];前部分为用户名,后部分为XMPP服务器域名。
假设朱丽叶([email protected])想和罗密欧([email protected])通话,他们两人的账号分别在 A.com 及 B.net 的服务器上。当朱丽叶输入消息并按下发送钮之后:
朱丽叶的XMPP客户端将她的消息发送到A.com XMPP服务器。
A.com XMPP服务器打开与B.net XMPP服务器的连接。
B.net XMPP服务器将消息寄送给罗密欧。如果他目前不在在线,那么存储消息以待稍后寄送。
罗密欧与朱丽叶两人的XMPP服务是由两家不同的企业所提供的,而他们彼此传讯时,不须拥有对方服务器的账号,也不须成为对方企业的会员。
2、XMPP特性
XMPP因为被Google Talk应用而被广大网民所接触。
XMPP与IMPP、PRIM、SIP(SIMPLE)合称四大IM协议主流,在此4大协议中,XMPP是最灵活的。
分布式:XMPP网络的架构和电子邮件十分相像;XMPP核心协议通信方式是先创建一个stream,XMPP以TCP传递XML数据流,没有中央主服务器。任何人都可以运行自己的XMPP服务器,使个人及组织能够掌控他们的即时传讯体验。
弹性佳:XMPP除了用在即时通信,还能用在网络管理、内容供稿、协同工具、文件共享、游戏、远程系统监控等。
安全:XMPP协议的服务器可以独立于公众XMPP网络(例如在企业内部网络中),而使用SASL及TLS等技术的可靠安全性,已内置于核心XMPP技术规格中。
3、与其他协议互联
XMPP协议的另一功能是运输(transports),也被称为网关(gateways),可允许用户通过网络使用其它协议。这可以是其他的即时通信协议,也可以是不同协议,如短信(SMS)或电子邮件。
各IM之间的互传:
4、XMPP协议通过HTTP运输
XMPP协议可以使用HTTP的方式有两种:轮询(polling)与绑定(binding)。
轮询现在不推荐,轮询:HTTP邮件存储在服务器端的数据库上,客户端必须一再地以HTTP的GET和POST的方式去抓取(以及刊出)其中的消息。
绑定的方式:客户端会保留一个长存的HTTP连接,等待一旦服务器有新的消息时,就立刻接收消息。因为轮询的结果往往是服务端没有新消息,这种推送的通知模式比轮询的方式更有效率。
5、再举个栗子,使用XMPP协议的客户端1与服务器端对话 :
客户端1 连接到一个XMPP服务器,发送一条消息(主题和内容均为“test 1449”)到客户端2,然后注销。
- 客户端1:
<?xml version="1.0"?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" to="XMPP服务器">
- XMPP服务器:
<stream:stream xmlns=‘jabber:client‘ xmlns:stream=‘http://etherx.jabber.org/streams‘ from=‘XMPP服务器‘ id=‘1461777714‘>
- 客户端1:
<iq type="set" id="auth_2" to="XMPP服务器" >
<query xmlns="jabber:iq:auth">
<username>客户端1</username>
<password>mypassword</password>
<resource>Work</resource>
</query>
</iq>
- XMPP服务器:
<iq from="XMPP服务器" id=‘auth_2‘ type=‘result‘/>
- 客户端1:
<message to="客户端[email protected]" >
<subject>test 1449</subject>
<body>test 1449</body>
</message>
<presence type="unavailable" >
<status>Logged out</status>
</presence>
</stream:stream>
- XMPP服务器:
</stream:stream>
八、TCP/IP深入
1、TCP/IP数据格式
便于大家观看,下面是翻译成中文后的图片:
每个字段的意思:
- Source Port(源端口)和Destination Port(目的端口):分别占用16位,用于区别主机中的不同进程,而IP地址是用来区分不同的主机的,源端口号和目的端口号配合上IP首部中的源IP地址和目的IP地址就能唯一的确定一个TCP连接。
- Sequence Number(数据序号):用来标识从TCP发端向TCP收端 发送的数据字节流,它表示在这个报文段中的第一个数据字节在数据流中的序号;主要用来解决网络报乱序的问题。
- Acknowledgment Number(确认序号):32位,包含发送确认的一端所期望收到的下一个序号,因此,确认序号应当是上次已成功收到数据字节序号加1。不过,只有当标志位中的ACK标志(下面介绍)为1时该确认序列号的字段才有效。主要用来解决不丢包的问题;
- Offset(偏移):给出首部中32 bit字的数目,需要这个值是因为任选字段的长度是可变的。这个字段占4bit(最多能表示15个32bit的的字,即4*15=60个字节的首部长度),因此TCP最多有60字节的首部。然而,没有任选字段,正常的长度是20字节;
- TCP Flags: TCP首部中有6个标志比特,它们中的多个可同时被设置为1,主要是用于操控TCP的状态机的,依次为URG,ACK,PSH,RST,SYN,FIN。每个标志位的意思如下:
URG:此标志表示TCP包的紧急指针域(后面马上就要说到)有效,用来保证TCP连接不被中断,并且督促中间层设备要尽快处理这些数据;
ACK:此标志表示应答域有效,就是说前面所说的TCP应答号将会包含在TCP数据包中;有两个取值:0和1,为1的时候表示应答域有效,反之为0;
PSH:这个标志位表示Push操作。就是指在数据包到达接收端以后,立即传送给应用程序,而不是在缓冲区中排队;
RST:这个标志表示连接复位请求。用来复位那些产生错误的连接,也被用来拒绝错误和非法的数据包;
SYN:表示同步序号,用来建立连接。SYN标志位和ACK标志位搭配使用,当连接请求的时候,SYN=1,ACK=0;连接被响应的时候,SYN=1,ACK=1;这个标志的数据包经常被用来进行端口扫描。扫描者发送一个只有SYN的数据包,如果对方主机响应了一个数据包回来 ,就表明这台主机存在这个端口;但是由于这种扫描方式只是进行TCP三次握手的第一次握手,因此这种扫描的成功表示被扫描的机器不很安全,一台安全的主机将会强制要求一个连接严格的进行TCP的三次握手;
FIN: 表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送FIN标志位的TCP数据包后,连接将被断开。这个标志的数据包也经常被用于进行端口扫描。
- Window:窗口大小,也就是有名的滑动窗口,用来进行流量控制;这是一个复杂的问题。
2、TCP/IP 三次握手
TCP协议之所以能提供可靠的连接 是因为三次握手。三次握手的目的是同步连接双方的序列号和确认号并交换 TCP窗口大小信息。
先简单说下上图中的 seq表示:Sequence Number(数据序号)。SYN:表示同步序号。ACK:不是TCP Flags里的标志,而是指Acknowledgment Number(确认序号)。
第一次握手:客户端发送连接请求报文段,将SYN位置为1,Sequence Number(数据序号)为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
第二次握手:服务器收到客户端的SYN报文段,对这个SYN报文段进行确认,设置Acknowledgment Number(确认序号)为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。
那么如果三次握手改成二次握手 会现在啥问题: 已失效的连接请求报文段突然又传送到了服务端,因而产生错误。详解:
- client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放 后 才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。
- 由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”
4、三次握手后就可以传送数据了。数据传送完毕后,就要断开TCP连接了,这就是TCP的第四次分手。
第一次分手:主机1(可以是客户端 或者 服务器端),设置Sequence Number和Acknowledgment Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;
第二次分手:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;
第三次分手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;
第四次分手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。
5、分个手也要四次,烦不烦,看看为啥分手要这么麻烦:
TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。
TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完了;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;然后主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就 中断了这次TCP连接。
6、四次分手过程中的状态变化。
FIN_WAIT_1: 其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。(主动方)
FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你(ACK信息),稍后再关闭连接。(主动方)
CLOSE_WAIT:表示在等待关闭。当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。(被动方)
LAST_ACK: 它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。(被动方)
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FINWAIT1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(主动方)
CLOSED: 表示连接中断。
九、HTTP详解
1、HTTP协议永远都是客户端发起请求,服务器回送响应。一个客户端向服务器端发出请求,然后服务器返回响应(response),连接就被关闭了。
2、做过Socket编程的人都知道,消息头/消息体”的分割方式是很常用的,消息头告诉对方这个消息是干什么的,消息体告诉对方怎么干。每一个HTTP包都分为HTTP头和HTTP体两部分,消息体是可选的,而消息头是必须的。每当我们打开一个网页,
HTTP 请求由三部分组成:请求行、 请求头和请求正文。请求行是指请求方法 URI 协议/版本,
格式如:POST /index.php HTTP/1.1 也就是:请求方式 /URL 协议/协议的版本。
3、请求方式
HTTP/2:这个版本是 2015年5月正式发布。HTTP/2通过支持请求与相应的多路重用来减少延迟,通过压缩HTTP头字段将协议开销降到最低,同时增加了对请求优先级和服务器端推送的支持。
HTTP/1.1协议中共定义了8种HTTP请求方法。
- GET:GET请求会显示请求指定的资源。一般来说GET方法应该只用于数据的读取,而不应当用于会产生副作用的非幂等的操作中。
GET会方法请求指定的页面信息,并返回响应主体,GET被认为是不安全的方法,因为GET方法会被网络蜘蛛等任意的访问。
- HEAD:HEAD方法与GET方法一样,都是向服务器发出指定资源的请求。但是,服务器在响应HEAD请求时不会回传资源的内容部分,即:响应主体。这样,我们可以不传输全部内容的情况下,就可以获取服务器的响应头信息。HEAD方法常被用于客户端查看服务器的性能。
- POST:POST请求会 向指定资源提交数据,请求服务器进行处理,如:表单数据提交、文件上传等,请求数据会被包含在请求体中。POST方法是非幂等的方法,因为这个请求可能会创建新的资源或/和修改现有资源。
- PUT:PUT请求会身向指定资源位置上传其最新内容,PUT方法是幂等的方法。通过该方法客户端可以将指定资源的最新数据传送给服务器取代指定的资源的内容。
- DELETE:DELETE请求用于请求服务器删除所请求URI(统一资源标识符,Uniform Resource Identifier)所标识的资源。DELETE请求后指定资源会被删除,DELETE方法也是幂等的。
- CONNECT:CONNECT方法是HTTP/1.1协议预留的,能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通信。
- OPTIONS:OPTIONS请求与HEAD类似,一般也是用于客户端查看服务器的性能。 这个方法会请求服务器返回该资源所支持的所有HTTP请求方法,该方法会用‘*‘来代替资源名称,向服务器发送OPTIONS请求,可以测试服务器功能是否正常。JavaScript的XMLHttpRequest对象进行CORS跨域资源共享时,就是使用OPTIONS方法发送嗅探请求,以判断是否有对指定资源的访问权限。 允许
- TRACE:TRACE请求服务器回显其收到的请求信息,该方法主要用于HTTP请求的测试或诊断。
4、在HTTP/1.1标准制定之后,又陆续扩展了一些方法。其中使用中较多的是PATCH 方法:
- PATCH:PATCH方法在2010年的RFC 5789标准中被定义。PATCH请求与PUT请求类似,同样用于资源的更新。二者有以下两点不同:
PATCH一般用于资源的部分更新,而PUT一般用于资源的整体更新。
当资源不存在时,PATCH会创建一个新的资源,而PUT只会对已在资源进行更新。
5、幂等性(Idempotence)
HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。幂等性属于语义范畴,正如编译器只能帮助检查语法错误一样,HTTP规范也没有办法通过消息格式等语法手段来定义它,这可能是它不太受到重视的原因之一。但实际上,幂等性是分布式系统设计中十分重要的概念,而HTTP的分布式本质也决定了它在HTTP中具有重要地位。
HTTP协议本身是一种面向资源的应用层协议,但对HTTP协议的使用实际上存在着两种不同的方式:一种是RESTful的,它把HTTP当成应用层协议,比较忠实地遵守了HTTP协议的各种规定;另一种是SOA的,它并没有完全把HTTP当成应用层协议,而是把HTTP协议作为了传输层协议,然后在HTTP之上建立了自己的应用层协议。HTTP幂等性主要针对RESTful风格的,幂等性并不属于特定的协议,它是分布式系统的一种特性;所以,不论是SOA还是RESTful的Web API设计都应该考虑幂等性。下面将介绍HTTP GET、DELETE、PUT、POST四种主要方法的语义和幂等性。
HTTP GET方法用于获取资源,不应有副作用,所以是幂等的。
HTTP DELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE http://www.xxxxx.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。
比较容易混淆的是HTTP POST和PUT。POST和PUT的区别容易被简单地误认为“POST表示创建资源,PUT表示更新资源”;而实际上,二者均可用于创建资源,更为本质的差别是在幂等性方面。在HTTP规范中对POST和PUT是这样定义的:
POST所对应的URI并非创建的资源本身,而是资源的接收者。比如用POST提交帖子,两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。而PUT所对应的URI是要创建或更新的资源本身。比如:PUT 创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。
比如,论坛网站中防止意外的重复发帖:
用POST 来实现发帖;用PUT 来实现更新帖。
本文为头条号作者发布,不代表今日头条立场。
收藏
16 条评论
评论
-
吃喝嫖赌样样通的小青年 31分钟前
写的不错,支持!
回复 1
-
某涂涂写写日记 2小时前
相当不错,正在学习这方面的知识。谢谢
回复 1
-
zuoxue88 3小时前
支持作者写的真不错
回复 0
-
终极iOS程序猿 3小时前
大家多多收藏。谢谢
回复 7
-
泾渭涛声98084146 1小时前
英文代码太多,谁能记住,那个层面都是看不见的东西,通讯系统的东西要从基础积累经验,尤其这些代码都是英文,很容易混淆,
回复