前言
前段时间使用XMPPFramework完成了一个仿微信的小项目,故特此来记录下即时通讯开发过程中的知识点以及存在一些问题,欢迎大家前来指教.
关于仿微信的demo在后面的篇章中会有github地址,请关注.本篇是关于Socket的相关介绍
一、Socket简介
1.Socket起源
socket起源于Unix,而Unix/Linux基本哲学之一就是:“一切即文件”,都可以用"打开open -> 读写write/read _> 关闭close"模式来操作。
简单来说socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO,关闭,打开),这些函数我们在后面进行介绍。
我们在传输数据的时候,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用成协议,应用层协议有很多,比如HTTP,FTP,TELNET等,也可以自己定义应用层协议。WEB协议使用HTTP协议作应用层协议,以封装HTTP文本信息,然后使用TCP/IP协议作传输层协议将它发到网络上。
2.Socket概念
Socket是一个针对TCP和UDP编程的接口,你可以借助它建立TCP/IP连接等等。而TCP和UDP协议属于传输层。而HTTP是个应用层的协议,它实际上也建立在 TCP协议之上.(HTTP是轿车,提供了封装或者是现实数据的具体形式;socket是发动机,提供了网络通信的能力)。
socket称为"套接字",适用于网络通信的方法。socket是对tcp/IP协议的封装,socket本身并不是协议,而是一个调用接口(api)。通过socket我们才能使用TCP/IP协议。Socket的出现只是使得程序员更方便地使用TCP/IP协议栈而已,是对TCP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口。
3.Socket通讯原理
socket是支持TCP/IP协议的网络通信的基本单元,包括:
- 传输控制协议
TCP(传输控制协议)
UDP(数据报文协议)
- 本地主机的IP地址
网络中设备的标示
不易记忆,可以用主机名
本地回环地址:127.0.0.1主机名:localhost
每台计算机都有一个127.0.0.1
如果 127.0.0.1ping不通,说明网卡不工作
如果本机地址ping不通,说明网线坏了
- 本地进程的协议端口号
用于标示进程的逻辑地址,不同进程的标示
有效端口:0~65535
其中0~1024由系统使用或者保留端口
开发中不要使用1024以下的端口
- 远程主机的IP地址
- 远程主机的协议端口号
通过IP找机器,通过端口找程序,通过协议确定如何传输数据
多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据.为了区别不同的应用程序进程和连接,计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(socket)接口.应用层可以和传输层通过socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务.
二、网络协议
网络七层由下往上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
其中物理层、数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象;
传输层、会话层、表示层和应用层则被称作主机层,是用户所面向和关心的内容。
http协议 对应于应用层tcp协议 对应于传输层ip协议 对应于网络层
三者本质上没有可比性。 何况HTTP协议是基于TCP连接的。
TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。
我们在传输数据时,可以只使用传输层(TCP/IP),但是那样的话,由于没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用应用层协议,应用层协议很多,有HTTP、FTP、TELNET等等,也可以自己定义应用层协议。WEB使用HTTP作传输层协议,以封装HTTP文本信息,然后使用TCP/IP做传输层协议将它发送到网络上。
Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
TCP/UDP
tcp和udp的区别
在这里就必须讲一下udp和tcp的区别了
TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。
UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。
关于TCP是一种流模式的协议,UDP是一种数据报模式的协议,这里要说明一下,TCP是面向连接的,也就是说,在连接持续的过程中,socket中收到的数据都是由同一台主机发出的(劫持什么的不考虑),因此,知道保证数据是有序的到达就行了,至于每次读取多少数据自己看着办。
而UDP是无连接的协议,也就是说,只要知道接收端的IP和端口,且网络是可达的,任何主机都可以向接收端发送数据。这时候,如果一次能读取超过一个报文的数据,则会乱套。比如,主机A向发送了报文P1,主机B发送了报文P2,如果能够读取超过一个报文的数据,那么就会将P1和P2的数据合并在了一起,这样的数据是没有意义的。
TCP三次握手和四次挥手
相对于SOCKET开发者,TCP创建过程和连接拆除过程是由TCP/IP协议栈自动创建的。因此开发者并不需要控制这个过程。但是对于理解TCP底层运作机制,相当有帮助。
因此在这里详细解释一下这两个过程。
TCP三次握手
所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。
三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时。将触发三次握手。
首先了解一下几个标志,SYN(synchronous),同步标志,ACK (Acknowledgement),即确认标志,seq应该是Sequence Number,序列号的意思,另外还有四次握手的fin,应该是final,表示结束标志。
第一次握手:客户端发送一个TCP的SYN标志位置1的包指明客户打算连接的服务器的端口,以及初始序号X,保存在包头的序列号(Sequence Number)字段里。
第二次握手:服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的序列号加1以,即X+1。
第三次握手:客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1。并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写序列号的+1。
tcp四次挥手
TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket
编程中,任何一方执行close()操作即可产生挥手操作。
其实有个问题,为什么连接的时候是三次握手,关闭的时候却是四次挥手?
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
三、TCP/UDP Socket
另外还有关于心跳包,断开重连,网络字节序等内容,该内容可以结合下面的CocoaSocket进行了解
四、CocoaSocket
用socket可以实现像QQ那样发送即时消息的功能。客户端和服务端需要建立长连接,在长连接的情况下,发送消息。客户端可以发送心跳包来检测长连接。
在iOS开发中使用socket,一般都是用第三方库AsyncSocket,不得不承认这个库确实很强大。
使用AsyncSocket的时候可以做一层封装,根据需求提供几个接口出来。比如:连接、断开连接、发送消息等等。还有接受消息,接受到的消息可以通过通知、代理、block等传出去。
具体的可以查询相关知识
使用CocoaSocket可以极大程度的方便使用socket,而不需要去记那些晦涩难懂的socket原语.
CococaSocket使用教程