在文章《linux基础编程:进程通信之System V IPC:消息队列,信号量,共享内存》开头部分,我们介绍了linux环境下的进程通信方式IPC分类。本节我们将介绍由贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)提出的IPC工具:套接字接口。
套接字机制是管道概念的一个扩展。凭借这种机制,客户或者服务器系统的开发工作既可以在本地单机运行,也可以跨网络进行分布式进程间进行。但是套接字的创建和使用和管道是有区别的,它明确地将通信的两端应该分为客户端和服务端。
要使用套接字进行进程通信之间,首先必须使用系统调用socket,从系统中分配一个类似文件描述符的套接字描述符,下面我们首先来学习一下套接字描述符。
套接字描述符
套接字由三个属性来确定一个套接字的基本特性:域(domain),类型(type)和协议(protocol),并且利用套接字的地址作为套接字的名字,从而使得其他进程可以找到。
套接字域(domain)
和管道通信不同,套接字可以在基于本地文件系统,以及各种类型的互联网的环境下的进程间通信。因此需要通过一个参数指定套接字的在通信过程中使用的通信介质(互联网,本地文件系统等)。我们把这个参数称为域。 在linux文档中介绍了AF_UNIX/AF_LOCAL,AF_INET,AF_INET6 等10多种域。而其中以下面三种种最为常见:
- AF_UNIX/AF_LOCAL:UNIX文件系统域,即以本地文件系统为通信介质。
- AF_INET/AF_INET6:IPv4/IPv6互联网域,即以IPv4/IPv6为通信介质。
套接字类型(type)
套接字类型是指创建套接字的应用程序要使用的通信服务类型。主要有下面三种:流套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW)。
- 流套接字(SOCK_STREAM):流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。
- 数据报套接字(SOCK_DGRAM):数据报套接字提供了一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。
- 原始套接字(SOCK_RAW):原始套接字相当于未定义规则的套接字,它的具体行为和它将要使用的套接字协议相关。
对于AF_UNIX/AF_LOCAL本地套接字来说,流套接字(SOCK_STREAM)相当于在本地进程之间建立起一条数据通道;数据报式套接字(SOCK_DGRAM)相当于单纯的发送消息,在进程通信过程中,理论上可能会有信息丢失、复制或者不按先后次序到达的情况,但由于其在本地通信,不通过外界网络,这些情况出现的概率很小。
对于AF_INET/AF_INET6互联网套接字来说,不同的套接字类型对应了不同的底层的网络协议。流套接字(SOCK_STREAM):网络套接字使用了传输控制协议,即TCP(The Transmission Control Protocol)协议,来保证实现可靠的数据服务。数据报套接字(SOCK_DGRAM):数据报套接字使用UDP(User Datagram Protocol)协议进行数据的传输。由于数据包套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。原始套接字(SOCK_RAW):原始套接字与标准套接字(标准套接字指的是前面介绍的流套接字和数据报套接字)的区别在于:原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送数据必须使用原始套接字。
另外,从linux2.6版本以后,还可以通过套接字类型来指定套接字的行为。通过上面三种和SOCK_NONBLOCK 进行OR操作,可以指定套接字为非阻塞套接字