`

Unix 域套接字概述

阅读更多
        Unix 域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方法,所用的 API 就是在不同主机上执行客户/服务器通信所用的套接字 API,可视为进程间通信(IPC)方法之一(POSIX 也把 Unix 域协议称为“本地 IPC”)。
        Unix 域提供了两类套接字:字节流套接字(类似 TCP)和数据报套接字(类似 UDP)。尽管也提供原始套接字,不过不曾见过使用。使用 Unix 域套接字有以下 3 个理由。
        (1)Unix 域套接字往往比位于同一个主机的 TCP 套接字快一倍。X Window System 就发挥了这个优势。当一个 X11 客户启动并打开到 X11 服务器的连接时,该客户会检查 DISPLAY 环境变量的值,其中指定了服务器的主机名、窗口和屏幕。如果服务器与客户处于同一个主机,客户就打开一个到服务器的 Unix 域字节流连接,否则打开一个 TCP 连接。
        (2)Unix 域套接字可用于同一个主机上的不同进程之间传递描述符。
        (3)Unix 域套接字较新的实现把客户的凭证(用户 ID 和组 ID)提供给服务器,从而能够提供额外的安全检查措施。
        Unix 域中用于标识客户和服务器的协议地址是普通文件系统中的路径名,不过这些路径名不是普通的 Unix 文件:除非把它们关联到 Unix 域套接字,否则无法读写这些文件。
        Unix 域套接字地址结构如下。
#include <sys/un.h>

struct sockaddr_un{
    sa_family_t  sun_family;      // AF_LOCAL
    char         sun_path[104];   // null-terminated pathname
};

        其中要注意的是,存放在 sun_path 数组中的路径名必须以空字符结尾。此外,因历史原因,虽然这里使用 104 来指明了 sun_path 的大小,但 POSIX 规范并没有明确规定 sun_path 的长度,因此应用程序应该在运行时使用 sizeof 运算符来计算 sockaddr_un 结构的大小。实现提供的 SUN_LEN 宏以一个指向 sockaddr_un 结构的指针为参数,并返回该结构的长度,其中包括路径名中的非空字节数。未指定地址通过以空字符串作为路径名指示,即 sun_path[0] 值为 0 的地址结构,它等价于 IPv4 的 INADDR_ANY 常值以及 IPv6 的 IN6ADDR_ANY_INIT 常值。
        下面这个示例创建一个 Unix 域套接字,往其上 bind 一个路径名,再调用 getsockname 输出这个绑定的路径名。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/un.h>
#include <sys/socket.h>

typedef struct sockaddr	SA;

int main(int argc, char **argv){
	if(argc != 2){
		printf("Usage: unixBind <pathname>\n");
		exit(2);
	}
	unlink(argv[1]);		// OK if this fails

	struct sockaddr_un	addr1, addr2;
	bzero(&addr1, sizeof(addr1));
	addr1.sun_family = AF_LOCAL;
	strncpy(addr1.sun_path, argv[1], sizeof(addr1.sun_path)-1);
	int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
	bind(sockfd, (SA *)&addr1, SUN_LEN(&addr1));

	socklen_t len = sizeof(addr2);
	getsockname(sockfd, (SA *)&addr2, &len);
	printf("bound name = %s, returned len = %d\n", addr2.sun_path, len);
	
	exit(0);
}

        程序运行结果如下:
$ umask
0022
$ ./unixBind /tmp/moose
bound name = /tmp/moose, returned len = 13
$ 
$ ./unixBind /tmp/moose                         # 再运行一次
bound name = /tmp/moose, returned len = 13
$ 
$ ls -l /tmp/moose
srwxr-xr-x. 1 lei root 0 3月  12 00:37 /tmp/moose
$ 
$ ls -lF /tmp/moose
srwxr-xr-x. 1 lei root 0 3月  12 00:37 /tmp/moose=
$ 

        创建的 Unix 域套接字的文件类型显示为“s”(有些系统把 Unix 域套接字视为 FIFO,从而显示为 p)。
        为了方便,Unix 域套接字提供了 socketpair 函数,它可以创建两个随后连接起来的套接字。
#include <sys/socket.h>
int socketpair(int family, int type, int protocol, int sockfds[2]);
                                    /* 返回值:若成功则为 0,否则为 -1 */

        这里,family 参数必须为 AF_LOCAL,protocol 参数必须为 0。type 参数可以是 SOCK_STREAM,也可以是 SOCK_DGRAM。sockfds 数组里就是保存的新创建的两个套接字描述符。
        这样创建的两个套接字不曾命名,也就是说其中没有设计隐式的 bind 调用。指定 type 参数为 SOCK_STREAM 得到的结果称为流管道,它与调用 pipe 创建的普通 Unix 管道类似,差别在于流管道是全双工的,即两个描述符都是既可读又可写的,而 POSIX 并不要求 pipe 返回两个全双工的描述符。
        虽然 Unix 域套接字用的也是套接字 API 函数,不过其中也还是存在如下一些差异和限制。
        (1)由 bind 创建的路径名默认访问权限应为 0777,并按照当前的 umask 值进行修正。
        (2)与 Unix 域套接字关联的路径名应该是一个绝对路径名,因为使用相当路径的话,对它的解析依赖于调用者的当前工作目录。
        (3)在 connect 调用中指定的路径名必须是一个当前已经绑定在某个打开的 Unix 域套接字上的路径名,而且它们的套接字类型(字节流或数据报)也必须一致(即 Unix 域字节流套接字不能连接到与 Unix 域数据报套接字关联的路径名,反之亦然)。
        (4)调用 connect 连接一个 Unix 域套接字涉及的权限测试等同于调用 open 以只写方式访问相应的路径名。
        (5)Unix 域字节流套接字类似于 TCP 套接字:它们都为进程提供一个无记录边界的字节流接口。
        (6)如果对于某个 Unix 域字节流套接字的 connect 调用发现该监听套接字的队列已满,调用就立即返回一个 ECONNREFUSED 错误。这一点不同于 TCP:如果 TCP 监听套接字的队列已满,TCP 监听端就忽略新到达的 SYN,而 TCP 连接发起端将数次发送 SYN 进行重试。
        (7)Unix 域数据报套接字类似于 UDP 套接字:它们都提供一个保留记录边界的不可靠的数据报服务。
        (8)在一个未绑定的 Unix 域套接字上发送数据报不会自动给这个套接字捆绑一个路径名,这一点不同于 UDP 套接字:在一个未绑定的 UDP 套接字上发送 UDP 数据报导致给这个套接字捆绑一个临时端口。这意味着除非数据报发送端已经捆绑一个路径名到它的套接字,否则数据报接收端无法发回应答数据报。类似地,对于某个 Unix 域数据报套接字的 connect 调用不会给本套接字捆绑一个路径名,这一点不同于 TCP 和 UDP。
分享到:
评论

相关推荐

    Java网络编程--Unix域协议:概述

    在Java中,使用Unix域协议编程时,可以利用Socket和ServerSocket类的构造函数,通过传入特定的Unix路径名来创建Unix域套接字。例如,ServerSocket的bind方法可以绑定到一个Unix路径,而Socket的connect方法可以连接...

    Java网络编程--Unix域协议:实现

    - `PRU_CONNECT`请求处理函数`unp_connect()`建立与其他Unix域套接字的连接。 17.11中提到的其他请求处理函数也执行类似的职责,如PRU_LISTEN、PRU_ACCEPT、PRU_SHUTDOWN等,它们是Unix域协议中实现通信的关键部分...

    libancillary:使用 Unix 域套接字在进程之间传递文件描述符

    库辅助使用 Unix 域套接字在进程之间传递文件描述符克隆概述这个库为可以在 Unix 域套接字上完成的黑魔法提供了一个简单的接口,比如将文件描述符从一个进程传递到另一个进程。 它应该 100% 符合 Single Unix ...

    UNIX网络编程卷1:套接字联网API(第3版)

    10. **UNIX域套接字**:除了网络套接字,书里还介绍了在同一主机内进程间通信的UNIX域套接字,它提供了更高效、更安全的通信方式。 以上只是《UNIX网络编程卷1:套接字联网API(第3版)》部分内容的概述,实际上,...

    TCP-IP详解卷三:TCP事务协议,HTTP,NNTP和UNIX域协议.rar

    UNIX域套接字允许在同一台机器上的进程之间直接交换数据,类似于网络套接字,但效率更高,因为它们不需要网络层的开销。根据数据类型,UNIX域套接字可以是流式(SOCK_STREAM,类似TCP)或数据报式(SOCK_DGRAM,类似...

    Unix Network Programming Volume 1,Third Edition The Sockets Networking API

    8. **高级主题**:涵盖了UNIX域套接字(用于同一主机上的进程间通信)、高性能服务器设计、多线程编程、套接字套件的安全性(SSL/TLS)以及网络时间协议(NTP)等。 9. **实例代码**:书中包含了大量的示例代码,...

    Unix网络编程(共两卷)

    此外,第二卷还涵盖了高级网络编程的主题,如UNIX域套接字、网络多路复用(select、poll和epoll)、非阻塞I/O、异步I/O模型,以及信号处理。这些技术可以帮助开发者设计出更加高效、灵活的网络应用程序。 最后,书...

    UNIX环境高级编程_第二版中文

    17.4.2 经由UNIX域套接字传送文件描述符  17.5 open服务器版本1  17.6 open服务器版本2  17.7 小结  习题  第18章 终端I/O  18.1 引言  18.2 综述  18.3 特殊输入字符  18.4 获得和设置终端属性...

    unix环境编程电子书

    473 17.3 UNIX域套接字 476 17.3.1 命名UNIX域套接字 477 17.3.2 唯一连接 478 17.4 传送文件描述符 482 17.4.1 经由基于STREAMS的管道传送文件描述符 484 17.4.2 经由UNIX域套接字传送文件描述符 486 ...

    unix 网络编程 卷2 进程间通信

    4. **Unix域套接字**:仅限于本地主机上的进程间通信,提供比网络套接字更高的效率。 #### 小结 《Unix网络编程卷2》深入分析了Unix系统中的进程间通信技术,涵盖了消息传递、共享内存、信号量以及套接字等多种IPC...

    网络编程教程,很好的一本写linux网络编程书,这是我上传的源码

     第十三章 UNIX域套接字和并发服务器的预创建技术  13.1 UNIX域套接字  13.1.1 UNIX域的地址结构  13.1.2 UNIX(套接字使用的示例  13.1.3 传递文件描述符  13.2 并发服务器的预创建技术  ...

    UNIX环境高级编程(第二版中文)

    17.4.2 经由UNIX域套接字传送文件描述符 486 17.5 open服务器版本1 493 17.6 open服务器版本2 498 17.7 小结 505 习题 505 第18章 终端I/O 507 18.1 引言 507 18.2 综述 507 18.3 特殊输入字符 512...

    UNIX系统编程

    同时,书中还讲解了如何使用UNIX域套接字实现本地进程间的通信,以及如何处理网络错误和异常情况。 ### 5. 系统调用与库函数 UNIX系统提供了大量的系统调用,允许程序员直接与操作系统内核交互。书中详细列举并...

    UNIX操作系统教程 张红光

    第1章绪论.1 1.1操作系统概述1 1.1.1建立操作系统的目标1 1.1.2操作系统是用户与计算机的接口1 1.1.3操作系统是资源管理器2 1.2UNIX系统的主要特性3 1.3UNIX系统的发展史4 1.4开源软件与UNIX的推广发展6 1.4.1开源...

    python-manhole:调试python应用程序的沙井

    概述docs 测试 包裹 Manhole是一种进程内服务,它将接受unix域套接字连接,并显示所有线程的堆栈跟踪和交互式提示。 它可以作为工作在任何时候都Python守护线程等待连接或一个信号处理器(停止你的应用程序,并等待...

Global site tag (gtag.js) - Google Analytics