资源预览内容
第1页 / 共55页
第2页 / 共55页
第3页 / 共55页
第4页 / 共55页
第5页 / 共55页
第6页 / 共55页
第7页 / 共55页
第8页 / 共55页
第9页 / 共55页
第10页 / 共55页
亲,该文档总共55页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
介绍Socket编程让你沮丧吗?从man pages中很难得到有用的信 息吗?你想跟上时代去编Internet相关的程序,但是为你在调用 connect。前的bind()的结构而不知所措?等等好在我已经将这些事完成了,我将和所有人共享我的知识了 如果你了解 C 语言并想穿过网络编程的沼泽,那么你来对地方 了。读者对象 这个文档是一个指南,而不是参考书。如果你刚开始 socket 编程并想找一本入门书,那么你是我的读者。但这不是一本完全 的 socket 编程书。平台和编译器这篇文档中的大多数代码都在 Linux平台PC上用GNU 的gcc成功编译过。而且它们在HPUX平台上用gcc也成功 编译过。但是注意,并不是每个代码片段都独立测试过。目录:1) 什么是套接字?2) Internet 套接字的两种类型3) 网络理论4) 结构体5) 本机转换6) IP 地址和如何处理它们7) socket ()函数8) bind ()函数9) connect ()函数10) listen ()函数11) accept ()函数12) send()和 recv()函数13) sendto ()和 recvfro m()函数14) close ()和 shutdown ()函数15) getpeername ()函数16) gethostname ()函数17) 域名服务( DNS)18) 客户-服务器背景知识19) 简单的服务器20) 简单的客户端21) 数据报套接字Socket22) 阻塞23) select()-多路同步I/O24) 参考资料什么是 socket?你经常听到人们谈论着“socket”,或许你还不知道它的确切 含义。现在让我告诉你:它是使用 标准Unix文件描述符(file descriptor)和其它程序通讯的方式。什么?你也许听到一些Unix 高手(hacker)这样说过:“呀,Unix中的一切就是文件!”那个家 伙也许正在说到一个事实: Unix 程序在执行任何形式的 I/O 的 时候,程序是在读或者写一个文件描述符。一个文件描述符只是 一个和打开的文件相关联的整数。但是(注意后面的话),这个文 件可能是一个网络连接,FIFO,管道,终端,磁盘上的文件或者 什么其它的东西。 Unix 中所有的东西就是文件!所以,你想和 Internet上别的程序通讯的时候,你将要使用到文件描述符。你必 须理解刚才的话。现在你脑海中或许冒出这样的念头: “那么我 从哪里得到网络通讯的文件描述符呢? ”,这个问题无论如何我 都要回答:你利用系统调用socket。,它返回套接字描述符(socket descriptor),然后你再通过它来进行send()和recv()调用。 “但是.”,你可能有很大的疑惑, “如果它是个文件描述符,那么 为什 么不用一般调用read()和write()来进行套接字通讯? ”简单 的答案是: “你可以使用! ”。详细的答案是: “你可以,但是使 用send()和recv()让你更好的控制数据传输。”存在这样一个情况: 在我们的世界上,有很多种套接字。有 DARPA Internet 地址 (Internet套接字),本地节点的路径名(Unix套接字),CCITT X.25 地址(你可以将X.25套接字完全忽略)。也许在你的Unix机器上 还有其它的。我们在这里只讲第一种:Internet套接字。Internet 套接字的两种类型什么意思?有两种类型的Internet套接字?是的。不,我在 撒谎。其实还有很多,但是我可不想吓着你。我们这里只讲两种。 除了这些, 我打算另外介绍的 Raw Sockets 也是非常强大的, 很值得查阅。那么这两种类型是什么呢? 一种是Stream Sockets(流格式), 另外一种是Datagram Sockets(数据包格式)。我们以后谈到它 们的时候也会用到 SOCK_STREAM 和 SOCK_DGRAM 。 数据报套接字有时也叫“无连接套接字”(如果你确实要连接的时 候可以用connect。)流式套接字是可靠的双向通讯的数据流。 如果你向套接字按顺序输出“1, 2”,那么它们将按顺序“1, 2”到 达另一边。它们是无错误的传递的,有自己的错误控制,在此不 讨论。有什么在使用流式套接字?你可能听说过telnet,不是吗? 它就使用流式套接字。你需要你所输入的字符按顺序到达,不是 吗?同样,WWW浏览器使用的HTTP协议也使用它们来下载 页面。实际上,当你通过端口80 telnet 到一个 WWW 站点,然 后输入 “GET pagename” 的时候,你也可以得到 HTML 的内 容。为什么流式套接字可以达到高质量的数据传输?这是因为它 使用了“传输控制协议(The Transmission Control Protocol)”,也叫“TCP” (请参考RFC-793获得详细资料。)TCP控制你的数据按 顺序到达并且没有错误。你也许听到“TCP”是因为听到过“TCP/IP”。这里的IP是 指“Internet协议”(请参考RFC-791。)IP只是处理Internet路由 而已。那么数据报套接字呢?为什么它叫无连接呢?为什么它是不 可靠的呢?有这样的一些事实:如果你发送一个数据报,它可能 会到达,它可能次序颠倒了。如果它到达,那么在这个包的内部 是无错误的。数据报也使用IP作路由,但是它不使用TCP。它 使用“用户数据报协议(User Datagram Protocol)”,也叫“UDP” (请参考 RFC-768。 )为什么它们是无连接的呢?主要是因为它并不象流式套接字 那样维持一个连接。你只要建立一个包,构造一个有目标信息的 IP 头,然后发出去。无需连接。它们通常使用于传输包-包信息。 简单的应用程序有:tftp, bootp等等。你也许会想: “假如数据丢失了这些程序如何正常工作? ”我 的朋友,每个程序在 UDP 上有自己的协议。例如, tftp 协议每 发出的一个被接受到包,收到者必须发回一个包来说 “我收到 了!”(一个“命令正确应答”也叫“ACK”包)。如果在一定时间内 (例如5秒),发送方没有收到应答,它将重新发送,直到得到 ACK。这一ACK过程在实现SOCK_DGRAM 应用程序的时候非 常重要。网络理论既然我刚才提到了协议层,那么现在是讨论网络究竟如何工 作和一些 关于 SOCK_DGRAM 包是如何建立的例子。当然, 你也可以跳过这一段, 如果你认为已经熟悉的话。现在是学习数据封装 (Data Encapsulation) 的时候了!它非常 非常重 要。它重要性重要到你在网络课程学(图1:数据封装) 习中无论如何也得也得掌握它。主要 的内容是:一个包,先是 被第一个协议(在这里是TFTP )在它的报头(也许 是报尾)包装 (“封装”),然后,整个数据(包括 TFTP 头)被另外一个协议 (在 这里是 UDP )封装,然后下一个( IP ),一直重复下去,直到硬件 (物理) 层( 这里是以太网 )。当另外一台机器接收到包,硬件先剥去以太网头,内核剥去IP和 UDP头,TFTP程序再剥去TFTP头,最后得到数据。现在我们终 于讲到声名狼藉的网络分层模型(Layered Network Model)。这种 网络模型在描述网络系统上相对其它模型有很多优点。例如,你 可以写一个套接字程序而不用关心数据的物理传输 (串行口,以 太网,连 接单元接口 (AUI) 还是其它介质),因为底层的程序 会为你处理它们。实际 的网络硬件和拓扑对于程序员来说是透 明的。不说其它废话了,我现在列出整个层次模型。如果你要参加网络 考试, 可一定要记住:应用层 (Application)表示层 (Presentation)会话层 (Session)传输层(Transport)网络层(Network)数据链路层(Data Link)物理层(Physical)物理层是硬件(串口,以太网等等)。应用层是和硬件层相隔最远 的-它 是用户和网络交互的地方。这个模型如此通用,如果你想,你可以把它作为修车指南。把它 对应到Unix,结果是:应用层(Application Layer) (telnet, ftp,等等)传输层(Host-to-Host Transport Layer) (TCP, UDP)Internet 层(I nternet Layer) (IP 和路由)网络访问层 (Network Access Layer) (网络层,数据链路层和物理 层) 现在,你可能看到这些层次如何协调来封装原始的数据了。看看建立一个简单的数据包有多少工作?哎呀,你将不得不使用 cat 来建立数据包头!这仅仅是个玩笑。对于流式套接字你要 作的是 send() 发 送数据。对于数据报式套接字,你按照你选择 的方式圭寸装数据然后使用sendto()。内核将为你建立传输层和 Internet 层,硬件完成网络访问层。 这就是现代科技。现在结束我们的网络理论速成班。哦,忘记告诉你关于路由的事 情了。但是我不准备谈它,如果你真的关心,那么参考 IP RFC。结构体终于谈到编程了。在这章,我将谈到被套接字用到的各种数 据类型。 因为它们中的一些内容很重要了。首先是简单的一个:socket描述符。它是下面的类型:int仅仅是一个常见的 int。 从现在起,事情变得不可思议了,而你所需做的就是继续看下去。 注 意这样的事实:有两种字节排列顺序:重要的字节 ( 有时叫 octet,即八 位位组)在前面,或者不重要的字节在前面。前一 种叫“网络字节顺序(Network Byte Order)”。有些机器在内部是 按照这个顺序储存数据,而另外 一些则不然。当我说某数据必 须按照 NBO 顺序,那么你要调用函数(例如 htons() )来将它从 本机字节顺序 (Host Byte Order) 转换过来。如果我没有 提到 NBO, 那么就让它保持本机字节顺序。我的第一个结构(在这个技术手册TM中)-struct sockaddr.。这个结 构 为许多类型的套接字储存套接字地址信息:struct sockaddr unsigned short sa_family; /* 地址家族 , AF_xxx */char sa_data14; /*14字节协议地址*/;sa_family 能够是各种各样的类型 ,但是在这篇文章中都是 AF_INET。sa_data包含套接字中的目标地址和端口信息。这 好像有点 不明智。为了处理struct sockaddr,程序员创造了一个并列的结构:struct sockaddr_in (in 代表 Internet。 )struct sockaddr_in short int sin_family; /* 通信类型 */ unsigned short int sin_port; /* 端口 */ struct in_addr sin_addr; /* Internet 地址 */ unsigned char sin_zero8; /*与sockaddr结构的长度相同*/ ;用这个数据结构可以轻松处理套接字地址的基本元素。注意 sin_zero (它被加入到这个结构,并且长度和 struct sockaddr 一样) 应该使用函数 bzero() 或 memset() 来全部置零。 同时,这一重 要的字节,一个指向sockaddr_in结构体的指针也可以被指向结 构体sockaddr并且代替它。这 样的话即使so
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号