当前位置:文档之家› socket编程中需要注意的问题

socket编程中需要注意的问题

socket编程中需要注意的问题
socket编程中需要注意的问题

Linux 套接字编程中的5 个隐患

在异构环境中开发可靠的网络应用程序

M. Tim Jones (mtj@https://www.doczj.com/doc/b211333992.html,), 资深软件工程师, Emulex

简介: Socket API 是网络应用程序开发中实际应用的标准API。尽管该API 简单,但是开发新手可能会经历一些常见的问题。本文识别一些最常见的隐患并向您显示如何避免它们。标记本文!

发布日期: 2005 年10 月08 日

级别:中级

访问情况 1563 次浏览

建议: 0 (添加评论)

如果不是所有的字符都能够在函数调用时排队,则最终的返回值是发送的字符数。由于send的MSG_DONTWAIT变量的无阻塞性质,函数调用在发送完所有的数据、一些数据或没有发送任何数据后返回。在这里忽略返回状态将导致不完全的发送和随后的数据丢失。

回页首隐患2.对等套接字闭包

UNIX 有趣的一面是您几乎可以把任何东西看成是一个文件。文件本身、目录、管道、设备和套接字都被当作文件。这是新颖的抽象,意味着一整套的API 可以用在广泛的设备类型上。

考虑read API 函数,它从文件读取一定数量的字节。read函数返回读取的字节数(最高为您指定的最大值);或者-1,表示错误;或者0,如果已经到达文件末尾。

如果在一个套接字上完成一个read操作并得到一个为0 的返回值,这表明远程套接字端的对等层调用了close API 方法。该指示与文件读取相同——没有多余的数据可以通过描述符读取(参见清单2)。

清单2.适当处理read API 函数的返回值

int sock, status;

sock = socket( AF_INET, SOCK_STREAM, 0 );

...

status = read( sock, buffer, buflen );

if (status > 0) {

/* Data read from the socket */

} else if (status == -1) {

/* Error, check errno, take action... */

} else if (status == 0) {

/* Peer closed the socket, finish the close */

close( sock );

/* Further processing... */

}

同样,可以用write API 函数来探测对等套接字的闭包。在这种情况下,接

收SIGPIPE信号,或如果该信号阻塞,write函数将返回-1 并设

置errno为EPIPE。

回页首隐患3.地址使用错误(EADDRINUSE)

您可以使用bind API 函数来绑定一个地址(一个接口和一个端口)到一个套接字端点。可以在服务器设置中使用这个函数,以便限制可能有连接到来的接口。也可以在客户端设置中使用这个函数,以便限制应当供出去的连接所使用的接口。bind最常见的用法是关联端口号和服务器,并使用通配符地址(INADDR_ANY),它允许任何接口为到来的连接所使用。

高位优先架构(比如PowerPC?)比低位优先架构(比如Intel? Pentium? 系列,其网络字节顺序是高位优先)有优势。这意味着,对高位优先的机器来说,在TCP/IP 内控制数据是自然有序的。低位优先架构要求字节交换——对网络应用程序来说,这是一个轻微的性能弱点。

通过套接字发送一个C 结构会怎么样呢?这里,也会遇到麻烦,因为不是所有的编译器都以相同的方式排列一个结构的元素。结构也可能被压缩以便使浪费的空间最少,这进一步使结构中的元素错位。

幸好,有解决这个问题的方案,能够保证两端数据的一致解释。过去,远程过程调用(Remote Procedure Call,RPC)套装工具提供所谓的外部数据表示(External Data Representation,XDR)。XDR 为数据定义一个标准的表示来支持异构网络应用程序通信的开发。

现在,有两个新的协议提供相似的功能。可扩展标记语言/远程过程调用(XML/RPC)以XML 格式安排HTTP 上的过程调用。数据和元数据用XML 进行编码并作为字符串传输,并通过主机架构把值和它们的物理表示分开。SOAP 跟随XML-RPC,以更好的特性和功能扩展了它的思想。参见参考资料小节,获取更多关于每个协议的信息。

回页首隐患5.TCP 中的帧同步假定

TCP 不提供帧同步,这使得它对于面向字节流的协议是完美的。这是TCP 与UDP(User Datagram Protocol,用户数据报协议)的一个重要区别。UDP 是面向消息的协议,它保留发送者和接收者之间的消息边界。TCP 是一个面向流的协议,它假定正在通信的数据是无结构的,如图1 所示。

图1.UDP 的帧同步能力和缺乏帧同步的TCP

图1 的上部说明一个UDP 客户端和服务器。左边的对等层完成两个套接字的写操作,每个100 字节。协议栈的UDP 层追踪写的数量,并确保当右边的接收者通过套接字获取数据时,它以同样数量的字节到达。换句话说,为读者保留了写者提供的消息边界。

现在,看图1 的底部.它为TCP 层演示了相同粒度的写操作。两个独立的写操作(每个100 字节)写入流套接字。但在本例中,流套接字的读者得到的是200 字节。协议栈的TCP 层聚合了两次写操作。这种聚合可以发生在TCP/IP 协议栈的发送者或接收者中任何一方。重要的是,要注意到聚合也许不会发生—— TCP 只保证数据的有序发送。

对大多数开发人员来说,该陷阱会引起困惑。您想要获得TCP 的可靠性和UDP 的帧同步。除非改用其他的传输协议,比如流传输控制协议(STCP),否则就要求应用层开发人员来实现缓冲和分段功能。

回页首调试套接字应用程序的工具

GNU/Linux 提供几个工具,它们可以帮助您发现套接字应用程序中的一些问题。此外,使用这些工具还有教育意义,而且能够帮助解释应用程序和TCP/IP 协议栈的行为。在这里,您将看到对几个工具的概述。查阅下面的参考资料了解更多的信息。

查看网络子系统的细节

软件,它可以帮助调试应用层协议。它的插入式架构(plug-in architecture)可以分解协议,比如HTTP 和您能想到的任何协议(写本文的时候共有637 个协议)。

回页首总结

套接字编程是容易而有趣的,但是您要避免引入错误或至少使它们容易被发现,这就需要考虑本文中描述的这5 个常见的陷阱,并且采用标准的防错性程序设计实践。GNU/Linux 工具和实用程序还可以帮助发现一些程序中的小问题。记住:在查看实用程序的帮助手册时候,跟踪相关的或“请参见”工具。您也许会发现一个必要的新工具。

参考资料

学习

?您可以参阅本文在developerWorks 全球站点上的英文原文。

?TCP 状态机有11 个状态。参见W. Richard Steven 的illustration from TCP/IP Illustrated, Volume 1一书。

?在Wikipedia 上探究Endianness的历史和含意。

?了解更多关于IBM 的开放式、可伸缩和可定制的Power Architecture的信息。

?从Programming in C课件阅读RPC/XDR 简介。

?获取更多关于XML-RPC 以及在Java? 应用程序中如何使用它的信息,请阅读“Java 编程中的XML-RPC” (developerWorks,2004 年1 月)。

?SOAP 以XML-RPC 的特性为基础。请在https://www.doczj.com/doc/b211333992.html,上查找规范、工具、教程和文章。

?SCTP兼有TCP 和UDP 的特性,以及可用性和可靠性。

?教程“Linux Socket 编程,第一部分” (developerWorks,2003 年10 月)讲解如何开始套接字编程以及如何构建一个通过TCP/IP 连接的echo 服务器和客户

端。“Linux Socket 编程,第二部分” (developerWorks,2004 年1 月)集中讨

论UDP 并且讲解如何用C 和Python 编写UDP 套接字应用程序(尽管代码会翻译为其他语言)。

?netstat 手册页提供有关各种使用netstat 的方法的细节。

?BSD Sockets Programming from a Multilanguage Perspective(作者M. Tim Jones),用6 种不同的语言介绍了套接字编程的技巧。

?在developerWorks Linux 专区上查找更多为Linux 开发人员提供的参考资料。

?Ethereal network protocol analyzer提供tcpdump 的功能,它具有图形用户界面和可伸缩的插入式架构。

?免费索取SEK for Linux(两张DVD),它包含来自DB2?、Lotus?、Rational?、Tivoli? 以及WebSphere? 的最新IBM 试用软件的Linux 版本。

?用IBM 试用软件在Linux 上构建您的下一个开发项目,可以直接在developerWorks 上下载。

讨论

?通过参与developerWorks blog加入developerWorks 社区。

关于作者

Tim Jones 是一名嵌入式软件工程师,他是GNU/Linux Application Programming、AI Application Programming以及BSD Sockets Programming from a Multilanguage Perspective等书的作者。他的工程背景非常广泛,从同步宇宙飞船的内核开发到嵌入式架构设计,再到网络协议的开发。Tim 是Emulex Corp. 的一名资深软件工程师。

相关主题
文本预览
相关文档 最新文档