`

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,类似...

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

    与网络套接字不同,UNIX域套接字不使用网络接口和网络层协议,而是直接通过主机的文件系统进行通信。这种方式提供了更高的通信效率和更低的延迟,特别适合于在同一主机上的进程间进行频繁的小数据量通信。 #### ...

    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环境编程电子书

    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系统编程

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

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

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

    UNIX环境高级编程_第2版.part2

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

    ACE继承层次图

    2. **ACE_TLI**:支持TCPIP和UNIX域套接字,基于TLI/XTI接口。 - **ACE_TLI_Acceptor**:用于接受TLI连接。 - **ACE_TLI_Stream**:用于处理TLI流式连接。 3. **ACE_SPIPE**:UNIX域套接字实现。 - **ACE_SPIPE_...

    Unix_Socket程序设计1.pdf

    通过对TCP和UDP的理解以及基本的套接字编程流程的学习,开发者可以更好地掌握如何利用Unix Socket来实现高效的通信服务。此外,通过具体的代码示例,可以帮助学习者更深入地理解Unix Socket编程的基本原理和技术细节...

    tcpIp_详解三卷套

    4. **UNIX域协议**:在单一操作系统内提供进程间通信的协议,包括流式和数据报类型的UNIX域套接字。 通过阅读《TCP/IP详解三卷套》,读者可以全面理解TCP/IP协议族的每个层面,不仅有助于网络理论的学习,更能为...

    netstat命令详解

    2. **Active UNIX domain sockets (with servers)** - 有源Unix域套接字,这部分主要显示了本地进程之间的通信信息。 - **Proto** - 套接字使用的协议类型,通常为UNIX。 - **RefCnt** - 引用计数,表示有多少进程...

    UNIX环境高级编程_第2版.part1

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

Global site tag (gtag.js) - Google Analytics