本文是 CocoaAsyncSocket 的 wiki 介绍文章,适合想要了解网络编程的朋友。
介绍 Sockets
如果你是网络编程新手,这里将会是开始了解的地方。使用 socket 与 处理文件会有很大的不同,即使它们的API 会很相似。在接触 socket 之前如果能学点网络相关的知识和概念能减少接下来的挫败感,这样才能走的更远。
本文会尽可能的从开发者使用的场景来简洁明了介绍相关知识点,同时不会跳过可能会导致问题的重要概念。
Sockets, Ports, and DNS - 我的天!
用网络的话来说,计算机就是包含一堆 sockets 的主机。一个 socket 就是网络连接通道的一端,另一端是另一个 socket。从自身角度来看,任何 socket 都是本地 socket,另一端就是远程 socket。
要建立连接,那么其中一个 socket 必须与另一个 socket 联系。要联系另一个 socket 则必须知道它的地址。每个 socket 都有一个地址。地址由两个部分组成:主机地址和端口号。主机地址也就是计算机的 IP 地址,端口号则是计算机上每个 socket 的唯一标识。
计算机可能包含多个网络接口,那它就会可能有多个 IP 地址。例如一台计算机会有以太网卡、调制解调器、WiFi、VPN 连接、蓝牙等等。除此之外还有一个连接到自身的特殊接口(叫做 loopback
或者有时叫做 localhost
)。
诸如 “google.com” 这类地址都对代表一个主机地址,但它本身并不是一个实际的主机地址。它只是一个 DNS 条目或 DNS名字,需要通过 DNS 查询来转换成实际的主机地址。
网络,嗯哼?
网络问题的关键在于它是不可靠的
。
假如你通过互联网发送一些数据,它可能通过 WiFi 或者蜂窝网络发送出去。又或者通过卫星发射到太空中。你甚至可能都不知道怎么发出去的。
但假设此时你知道所有的都会通过常规互联网发送。那这时候通信总该是 100% 可靠了吧对吗?错了!我说的可不是断电和切断电源这种说法。
所有发送或接收的数据都被分解成小的数据包。这些数据包被推到网络上,然后到达决定它们去向的路由。但在网络繁忙的时候,路由可能会发生数据包过载。数据包的传入速度快过路由觉得目的地的速度。那会发生什么呢?全球每天发生数百万次:路由开始丢弃数据包。
除了网络上的丢包,接收方的计算器也会被强制丢包。如果计算机过载,或者应用程序没有尽快的从系统里读取数据。还有可能数据包在传输过程中受到电气干扰。并且我都还没说 WiFi 和网卡的各种问题。
如果你不熟悉网络,那你可能会认为一切运转正常是一个奇迹。实际上,奇迹源自过去几十年来网络协议的不断完善和理解并高效使用它们的开发者。(正是你自己)
来看看协议
您可能会列出许多与计算机网络有关的协议:
HTTP, FTP, XMPP, POP, IMAP, SMTP, DHCP, DNS, VoIP, SIP, RTP, RTCP, ...
但是,这些协议中的每个协议都位于处理该网络的另一个协议之上。这些较低级别的协议处理了大多数网络方面的内容,因此应用程序层协议(上面列出的那些协议)可以专注于应用程序方面。
上面列出的“应用层协议”位于“传输层协议”之上。在上面列出的所有协议中,仅使用两种传输层协议:TCP和UDP。
UDP
用户数据报协议(UDP)是这两个中最简单的一个。你只能将少量数据放入UDP数据包,然后按其方式发送。然后…没了,就这么简单。也不保证消息能够送达。如果你一个接一个的发送多个包,它也不保证送达的时候是按顺序来的。似乎很不可靠,不是吗?它的弱点也是它最强大的地方。如果你要发送一些跟时间强相关的数据,例如 VoIP 电话,你不想把时间浪费到丢包重传这种事情上,因为丢失的音频数据就算重新发送成功也太迟了。实际上流媒体是 UDP 应用最广泛的地方。
UDP 还有一个优点就是建立连接不需要握手。这样的话连接就能快速建立来处理具体事情。这就是为什么 DNS 要使用 UDP 的原因了。
TCP
传输控制协议(TCP)可能是我们用到的最频繁的协议了。浏览网页、发送邮件、与好友即时聊天等等可能都用到了 TCP。
TCP 设计用于进行长时间对话的。因此它需要首次握手,然后数据才可以在一段时间内来回流动。但是 TCP 最棒的事情是面对不可靠的网络环境时让数据传输变得可靠。因此它为我们做了很多很酷的工作。如果你用 TCP 传送一些数据的时候某一部分丢失了,TCP 会找到那部分并重新发送他们。并且 TCP 还会保证所有信息是按正确的顺序送达的。等等,它还有一个功能呢!它能侦测网络传输时的拥挤状况来自动的调整让每个人都能正常使用。
因此,有很多使用TCP的充分理由,它非常适合许多网络任务。另外,您可以通过TCP发送的数据量没有限制。它用来打开一个双向数据流,应用层来决定数据的结构。
那我该选择哪种?
那么。。。UDP 和 TCP 我该怎样使用它们呢? CocoaAsyncSocket 提供了它们的实现吗?不是的,想想看,既然 TCP 和 UDP 到处在使用,那么自然是操作系统提供它们的实现。如果你打开你的终端输入 man stocket
就会看到低级的 BSD socket API。这个库的作用实际上就是帮我们封装好了 API 方便使用而已。
因此 CocoaAsyncSocket 能极大的简化我们的网络开发。但网络编程依然很棘手,建议在开发之前再继续了解下下面的文章: