Socket
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。
常见的socket类型有两种:流式Socket和数据报式Socket。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。
TCP与UDP的区别
建立连接的的方式
- TCP
(1)第一次握手:
Client将标志位SYN置为1,随机产生一个值seq=X,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
(2)第二次握手:
Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=X+1,随机产生一个值seq=Y,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
(3)第三次握手:
Client收到确认后,检查ack是否为X+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=Y+1,并将该数据包发送给Server,Server检查ack是否为Y+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
(1)第一次挥手:
Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:
Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:
Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:
Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。
- UDP
我们都知道 TCP 是面向连接的、可靠的、有序的传输层协议,而 UDP 是面向数据报的、不可靠的、无序的传输协议,所以 UDP 压根不会建立什么连接。
就好比发短信一样,UDP 只需要知道对方的 ip 地址,将数据报一份一份的发送过去就可以了,其他的作为发送方,都不需要关心。
数据发送方式的差异
TCP:由于 TCP 是建立在两端连接之上的协议,所以理论上发送的数据流不存在大小的限制。但是由于缓冲区有大小限制,所以你如果用 TCP 发送一段很大的数据,可能会截断成好几段,接收方依次的接收。
UDP:由于 UDP 本身发送的就是一份一份的数据报,所以自然而然的就有一个上限的大小。
数据有序性的差异
TCP:对于 TCP 来说,本身 TCP 有着超时重传、错误重传、还有等等一系列复杂的算法保证了 TCP 的数据是有序的,假设你发送了数据 1、2、3,则只要发送端和接收端保持连接时,接收端收到的数据始终都是 1、2、3。
UDP:而 UDP 协议则要奔放的多,无论 server 端无论缓冲池的大小有多大,接收 client 端发来的消息总是一个一个的接收。并且由于 UDP 本身的不可靠性以及无序性,如果 client 发送了 1、2、3 这三个数据报过来,server 端接收到的可能是任意顺序、任意个数三个数据报的排列组合。
可靠性的差异
TCP:TCP 内部的很多算法机制让他保持连接的过程中是很可靠的。比如:TCP 的超时重传、错误重传、TCP 的流量控制、阻塞控制、慢热启动算法、拥塞避免算法、快速恢复算法 等等。所以 TCP 是一个内部原理复杂,但是使用起来比较简单的这么一个协议。
UDP:UDP 是一个面向非连接的协议,UDP 发送的每个数据报带有自己的 IP 地址和接收方的 IP 地址,它本身对这个数据报是否出错,是否到达不关心,只要发出去了就好了。
使用场景
- UDP
对实时性要求高:比如实时会议,实时视频这种情况下,如果使用 TCP,当网络不好发生重传时,画面肯定会有延时,甚至越堆越多。如果使用 UDP 的话,即使偶尔丢了几个包,但是也不会影响什么,这种情况下使用 UDP 比较好;
多点通信:TCP 需要保持一个长连接,那么在涉及多点通讯的时候,肯定需要和多个通信节点建立其双向连接,然后有时在NAT环境下,两个通信节点建立其直接的 TCP 连接不是一个容易的事情,而 UDP 可以无需保持连接,直接发就可以了,所以成本会很低,而且穿透性好。这种情况下使用 UDP 也是没错的。
- TCP
其他场景,基本都是TCP更加适合。
第三方库
CocoaAsyncSocket:https://github.com/robbiehanson/CocoaAsyncSocket
CocoaAsyncSocket provides easy-to-use and powerful asynchronous socket libraries for Mac and iOS. The classes are described below.
参考链接:
http://www.ruanyifeng.com/blog/2017/06/tcp-protocol.html