2.1. 两种 Internet Sockets
这是什麽?有两种 Internet sockets 吗?
是的,喔不,我骗你的啦。其实有更多种 Internet sockets,只是我不想吓唬你。所以这里我只打算讨论两种,不过我还会告诉你"Raw Sockets",这是很强大的东西,所以你应该要好好研究一下它们。
译注:
一般的 socket 只能读取 transport layer 传输层以上[不含]的数据,raw socket 一般用在设计 network sniffer,可以让应用程序取得网路数据包底层的数据[如 TCP 层丶IP 层,甚至 link layer socket 可以读取到 link layer 层],并用以分析数据包。这份教程不会谈到这类的编程,有兴趣的读者可自行参考:Unix Network Programming Vol. 1丶TCP/IP 网路程式实验与设计或 libpcap。
好吧,不聊了。那到底是有哪两种 Internet sockets 呢?
其中一个是"Stream Sockets"(串流式 Sockets);而另一个是"Datagram Sockets"(讯息式 Sockets),之後我们分别以"SOCK_STREAM"与"SOCK_DGRAM"来表示。Datagram sockets 有时称为"无连接的 sockets"(connectionless sockets)(虽然它们也可以用 connect(),如果你想这麽做的话,请见後面章节的 connect())。
Stream sockets 是可靠的丶双向连接的通讯串流。若你以"1丶2"的顺序将两个项目输出到 socket,它们在另一端则会以"1丶2"的顺序抵达。而且不会出错。
哪里会用到 stream sockets 呢?
好的,你应该听过 telnet 软件吧,不是吗?它就是用 stream sockets。你所输入的每个字都需要按照你所输入的顺序抵达,有吗?网页浏览器所使用的 HTTP 协议也是用 stream sockets 取得网页。的确,若你以 port 80 telnet 到一个网站,并输入"GET / HTTP/1.0",然後按两下 Enter,它就会输出 HTML 给你!
Stream sockets 是如何达成如此高品质的数据传送呢?
它们用所谓的"The Transmission Control Protocol"(传输控制协议),就是常见的"TCP"(TCP 的全部细节请参考 RFC 793[6])。TCP 保证你的数据可以依序抵达而且不会出错。你以前可能听过"TCP"是"TCP/IP"比较优的部分,这边的"IP"是指"Internet Protocol"(互联网协议,请见 RFC 791[7])。IP 主要处理 Internet routing(互联网路由),通常不保障数据的完整性。
酷喔。那 Datagram socket 呢?为什麽它们号称无连接呢?这边有什麽好主意?为什麽它们 是不可靠的?
好,这里说明一下现况:如果你送出一个 datagram(信息数据包),它可能会顺利到达丶可能不会按照顺序到达,而如果它到达了,数据包的数据就是正确的。
译注:
TCP 会在传输层对将上层送来的过大数据分割成多个 TCP 段(TCP segments),而 UDP 本身不会,UDP 是信息导向的(message oriented),若 UDP 信息过大时(整体数据包长度超过 MTU),则会由 host 或 router 在 IP 层对数据包进行分割,将一个 IP packet 分割成多个 IP fragments。IP fragmention 的缺点是,到达端的系统需要做 IP 数据包的重组,将多个 fragments 重组合并为原本的 IP 数据包,同时也会增加数据包遗失的可能性。如将一个 IP packet 分割成多个 IP fragments,只要其中一个 IP fragment 遗失了,到达端就会无法顺利重组 IP 数据包,因而造成数据包的遗失,若是高可靠度的应用,则上层协议需重送整个 packet 的数据。
Datagram sockets 也使用 IP 进行 routing(路由),不过它们不用 TCP;而是用"UDP,User Datagram Protocol"(用户数据包协议,请见 RFC 768 [8])。
为什麽它们是无连接的?
好,基本上,这跟你在使用 stream socket 时不同,你不用维护一个开启的连接,你只需打造数据包丶给它一个 IP header 与目的资料丶送出,不需要连接。通常用 datagram socket 的时机是在没有可用的 TCP stack 时;或者当一些数据包遗失不会造成什麽重大事故时。这类应用程序的例子有:tftp(trivial file transfer protocol,简易文件传输协议,是 FTP 的小兄弟),多人游戏丶串流音乐丶影像会议等。
"等一下!tftp 和 dhcpd 是用来在一台主机与另一台之间传输二进制的应用数据!你如果想要应用程序能在数据抵达时正常运作,那数据就不能遗失阿!这是什麽黑魔法?"
好,我的人类朋友,tftp 与类似的程序会在 UDP 的上层使用它们自己的协议。比如:tftp 协议会报告每个收送的数据包,到达端必须送回一个数据包表示:"我收到了!"[一个 "ACK"数据包]。若原本数据包的传送端在五秒内没有收到回应,这表示它该重送这个数据包,直到收到 ACK 为止。在实作可靠的 SOCK_DGRAM 应用程序时,这个回报的过程很重要。
对於无需可靠度的(unreliable)应用程序,如游戏丶音效丶或影像,你只需忽略遗失的数据包,或也许能试着用技巧弥补回来。(雷神之锤的玩家都知道的一个技术名词的影响:accursed lag。在这个例子中,"accursed"(受到诅咒)这个字代表各种低级的意思)。
为什麽你要用一个不可靠的底层协议?
有两个理由:第一个理由是速度,第二个理由还是速度。忘了这个数据包是比较快的方式,相较之下,持续追踪全部的数据包否安全抵达,并确保依序抵达是比较慢的。如果你想要传送聊天讯息,TCP 很好;不过如果你想要替全世界的玩家,每秒送出 40 个位置更新的数据,且若遗失一到两个数据包并不会有太大的影响时,此时 UDP 是一个好的选择。
译注:
stream(串流式)socket 是指应用程序要传输的数据就如水流(串流)在水管中传输一般,经由这个 stream socket 流向目的,串流式 socket 是数据会由传输层负责处理遗失丶依序送达等工作,以在传输层确保应用程序所送出的数据能够可靠且依序抵达,而应用程序若对数据有可靠与依序的需求时,使用 stream socket 就不用自行处理这类的工作。
datagram(信息式)socket 是基於讯息导向的方式传送数据,应用程序送出的每笔数据会如平信的概念送出,由於遶送数据包的路径可能会随着网路条件而改变,每笔数据抵达的顺序不一定会按照送出的顺序抵达,并且如平信般,信件可能在递送过程遗失,而寄件人并无法知道是否递送成功。
初步简单知道应用这两种 sockets 的时机:当需要数据能完整送达目地时,就使用 stream socket,若是部分数据遗失也无妨时,就可以使用 datagram socket。
Last modified 10mo ago