2.什么是套接字(socket)
你可能听过“套接字”并想搞清楚这是什么。套接字就是:一种通过标准unix文件描述符与其它程序通讯的方法(或通道)。
什么?
好的-你可能听过一些unix黑客说,“天啊,unix中所有东西都是文件!”这个事实是说unix程序在做一些I/O操作时是通过读写一个文件描述符来实现的。文件描述符是一个简单的整数它关联于一个打开的文件。但是这个文件可以是一个网络连接,一个FIFO,一个中断,或者一个实实在在存在磁盘中的文件,或是其它什么东西。总之unix系统中的一切都是文件!所以你想通过互联网与另一个程序通讯那么就要通过这样一个文件描述符,你要相信这一点。
“我从那里得到这个文件描述符进行网络通讯,小滑头先生?”这也许是你的新问题,我正要回答这个问题:你可以使用socket()系统调用。它返回一个套接字描述符,这样你就可以通过它使用专用的send()和recv()套接字进行通讯了。
“等一下!”你可能现在惊呼,套接字是一个文件描述符,为什么不使用通常的read()和write()调用去通信?简短的回答是:“可以!”长一点的回答是:“可以,但是send()和recv()通常更有利于你进行数据的传输。”
“接下来呢?”看看这个:有多种套接字。DARPA网络地址(互联网套接字),本地路径名称(unix套接字),CCITTX.25地址,可能还有其它种类。本文档仅讨论第一种:互联网套接字。
2.1.两种类型的互联网套接字
这是什么?这里有两种互联网套接字?是的。呵呵,不是。我开个玩笑。其它有很多种,我是不想吓到你。我只谈两种类型,我还想告诉你原生套接字功能强大,你可不要小看了它。
好了,好了!那两种?一种是“流式套接字”;另一种是“数据报套接字”后面分别记为“SOCK_STREAM”和“SOCK_DGRAM”。数据报套接字也称为“无连接套接字”。(如果你非要连接也可以,请看后面的connect()使用。)
流式套接字是可靠的双向通信流。如果你向套接字发送了两个数据项按顺序“1,2”,接收方也会按顺序“1,2”收到数据。并且是无错的,我是如此的确定,事实是确实是无错的。如果没有人打扰我可能开始唱歌了“la la la”。
什么场合使用流式套接字?嗯!你可能听说过telnet应用程序,是吗?它使用流式套接字。终端收到的字符顺序必须与你键入的一致,对吗?还有网页浏览器使用http协议,它使用流式套接字来获得页面。事实上,如果你使用telnet通过80端口去访问web站点,键入”GET /HTTP/1.0”并按下两次回车键,你就会得到html文件了。
流式套接字如何实现高质量数据传输?他使用一个称作“传输控制协议”也叫作“TCP”(参考RFC793获得详细信息)。TCP保证了数据传输的顺序和无差错。你可能知道TCP是“TCP/IP”的前半部分,这里的“IP”是“网际协议”(参考RFC791)IP主要处理互联网路由但是不保证数据完整。
帅呆了!在什么场合使用数据报套接字?为什么称为无连接?它要用来处理那些情况?为什么是不可靠的?不要着急。如果你发送一个数据报它可能会被收到,而且可能不是按顺序收到。如果收到了,数据报中的数据是无错的。
数据报套接字也使用IP进行路由,但是不使用TCP,而是使用“UDP”(用户数据报协议)(参考RFC768)。
为什么是无连接的?根本的原因是你没有像流式套接字一样去保持一个打开的连接。你仅仅创建了包,打了个有目的地址信息的IP头,然后就把包发送出去了并不需要连接。它通常用于TCP栈不能使用或数据包丢失影响不大的情况。简单的应用:fttp(简单文件传输协议,一个ftp协议的兄弟协议。)dhcpcd(dhcp客户端),多玩家游戏,流媒体音乐或视频会议等等。
等一下,等一下!tftp和dhcpcd都是用来从一台主机向另一台主机传输二进制数据的应用。数据是不能丢失的,否则无法完成工作。难道你这里有什么魔法?
呵呵!我的朋友,你可真聪明。Tftp及其它相似的应用在UDP之上有自己的协议。举个例子:tftp协议表现为接收端收到包后就会发送一个回执包(ACK包)表示数据已经收到。如果发送端在5秒钟后还没有收到ACK包,发送端将重发,直到收到ACK包为止。这个ACK包方法对于需要在数据报套接字上进行可靠传输非常重要。对于不可靠的应用,如游戏,音乐,视频你可以忽略丢失的包或者试着进行补偿。
为什么你要使用一个不可靠的协议?两个原因:第一个是速度,另一个还是速度。发送了就不管了总是比跟踪是否收到保证顺序要快的多。如果你发送聊天信息TCP是适合的,但是你要是1秒钟内发送给40个在不同位置的玩家更新信息,可能会丢失1、2个包担影响不大,这个时候UPD就是一个不错的选择。
2.2.底层网络技术
已经提到过协议层了,是时候谈谈网络工作原理了,接下来有一些例子说明数据包套接字的创建。实际上你完全可以跳过下面本小节,但是这上很好的背景知识。
数据包装图
嗨!伙计,该学习数据包装了!这是相当重要的,如果你选择网络课程,可能就会重点学习这部分内容。基本上是这样的:一个数据包产生后由TFTP协议给它包装一个头部(当然还有个尾部),然后由UDP协议对这个整体进行包装,再接下来交给下一个(也就是IP协议),这样到硬件层加上以太网头就发送了。
当另一台计算机收到包,硬件剥掉以太网头,系统剥掉IP和UDP头,TFTP程序去掉TFTP头,最后获得了数据。
现在我们说一下著名的网络层模型(也称为:IOS/OSI)。这个网络模型描述了一个系统的网络功能,比其它模型更有优势。例如,你可以写一个套接字程序而不用关心物理(串口,以太网或其它)上如何传输的,因为程序已经为你处理好了这一切。实际上网络、硬件及其拓扑结构对套接字程序员是透明的。
我将列出层模型,记住这个,经常会考到的。
l 应用层
l 表示层
l 会话层
l 传输层
l 网络层
l 数据链路层
l 物理层
物理层是硬件(串口、以太网或其它),就像你看到的应用层离物理层比较远----这就是用户使用网络的接口。
这个模型是如此的普遍你甚至可以你使用汽车维修手册一样(译者:美国人可能人人都有汽车吧,我现在连个房奴都当不上。呵呵!)。
在unix上一个层模型如下:
l 应用层(telnet、ftp等等)
l 主机到主机层(Tcp、Udp)
l 网络层(IP和路由)
l 网络访问层(以太网、wi-fi或其它)
你可能已经看过层包装原始数据的方法了,如果没有可以看前面的内容。
多少工序可以创建一个简单的包?
天啊!你把”cat”当包头使用!开个玩笑。(译者:这并不仅仅是个玩笑,你完全可以自己定义自己包头。)流式套接字使用send()发送数据。你使用数据报套接字则需要使用sendto()发送数据。系统创建传输层和网络层,硬件处理网络层。啊!多现代化的技术!
该结束我们简明的网络理论了。嗯!是的,我忘记告诉你一些关于路由的事了。没什么,没什么!对了,我根本不想说关于路由的任何事。路由器根据包的IP头,查询它的路由表。呵呵,呵呵!如果你真的关心这个自己去查IPRFC吧。说真的如果你从不学习这个,也没什么关系。
《第三篇完》