文档章节

网络编程学习——Unix域协议

thanatos_y
 thanatos_y
发布于 2016/04/20 16:27
字数 1903
阅读 49
收藏 0

1 概述

  Unix域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方式,所用API就是在不同主机上执行客户/服务器通信所用的API(套接字API)。

  Unix域提供两类套接字:字节流套接字(类似于TCP)和数据报套接字(类似UDP)尽管也提供原始套接字,不过它的语义不曾见于任何文档,作者们也未见过任何使用它的程序,POSIX也没有它的定义。

  使用Unix域套接字有以下3个理由。

  1. 在BSD的实现中,Unix域套接字往往比通信两端位于同一个主机的TCP套接字快出一倍。X Window System发挥了Unix域套接字的这个优势。当一个X11客户启动并打开到X11服务器的连接时,该客户检查DISPLAY环境变量的值,其中指定服务器的主机名、窗口和屏幕。如果服务器与客户出于同一主机,客户就打开一个到服务器的Unix域字节流连接,否则打开一个到服务器的TCP连接。

  2. Unix域套接字可用于在同一个主机上的不同进程之间传递描述符。

  3. Unix域套接字较新的实现把客户的凭证(用户ID和组ID)提供给服务器,从而能够提供额外的安全检查措施。

  Unix域中用于标识客户和服务器的协议地址是普通文件系统中的路径名。这些路径名不是普通的Unix文件:除非把它们和Unix域套接字关联起来, 否则无法读写这些文件。

2 Unix域套接字地址结构

  Unix域套接字地址结构如下。

#include <sys/un.h>
/* Structure describing the address of an AF_LOCAL (aka AF_UNIX) socket.  */
struct sockaddr_un
  {
    __SOCKADDR_COMMON (sun_);
    char sun_path[108];        /* Path name.  */
  };

  存放在sun_path数组中的路径名必须以空字符结尾。

例子:Unix域套接字的bind调用

  下面程序创建一个Unix域套接字,往其上bind一个路径名,再调用getsockname输出这个绑定的路径名。

3 socketpair函数

  socketpair函数创建两个随后连接起来的套接字。不函数仅适用于Unix域套接字。

#include <sys/socket.h>
/* Create two new sockets, of type TYPE in domain DOMAIN and using
   protocol PROTOCOL, which are connected to each other, and put file
   descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
   one will be chosen automatically.  Returns 0 on success, -1 for errors.  */
extern int socketpair (int __domain, int __type, int __protocol,
               int __fds[2]) __THROW;

  __domain参数必须为AF_LOACL,__protocol参数必须为0。__type参数既可以是SOCK_STREAM,也可以是SOCK_DGRAM。新建的两个套接字描述符作为__fds[0]和__fds[1]返回。

  这样创建两个套接字不曾命名,也就是说其中没有涉及隐式的bind调用。指定type参数为SOCK_STREAM调用socketpair得到的结果称为流管道(pipe)。它与调用pipe创建的普通Unix管道类似,差别在于流管道是全双工的,即两个描述符都是既可读又可写的。

4 套接字函数

  1. 由bind创建的路径名默认访问权限应为0777,并按照当前umask值进行修正。

  2. 与Unix域套接字关联的路径名应该是一个绝对路径名,而不是一个相对路径名。

  3. 在connect调用中指定路径名必须是一个当前绑定在某个打开的Unix域套接字上的路径名,而且它们的套接字类型(字节流或数据报)也必须一致。

  4. 调用connect连接一个Unix域套接字涉及的权限设置测试等同于调用open以只写方式访问相应的路径名。

  5. Unix域字节流套接字类似TCP套接字:它们都为进程提供一个无记录边界的字节流接口。

  6. 如果对于某个Unix域字节流套接字的connect调用发现这个监听套接字的队列已满,调用就立即返回一个ECONNREFSUED错误。

  7. Unix域数据报套接字类似于UDP套接字:它们都提供一个保留记录边界的不可靠的数据报服务。

  8. 在一个未绑定的Unix域套接字上发送数据报不会自动给这个套接字捆绑一个路径名,这一点不同于UDP套接字:在一个未绑定的UDP套接字上发送UDP数据报导致给这个套接字捆绑一个临时端口。

5 描述符传递

  当考虑从一个进程到另一个进程传递打开的描述符时,我们通常会想到:

  • fork调用返回之后,子进程共享父进程的所有打开的描述符;

  • exec调用执行之后,所有描述符通常保持打开状态不变。

  当前的Unix系统提供了用于从一个进程向任一其他进程传递一打开的描述符的方法。也就是说,这两个进程之间无需存在亲缘关系,譬如父子进程关系。这种技术要求首先在这两个进程之间创建一个Unix域套接字,然后使用sendmsg跨这个套接字发送一个特殊消息。这个消息由内核来专门处理,会把打开的描述符从发送进程传递到接收进程。

  在两个进程之间传递描述符涉及的步骤如下。

  1. 创建一个字节流的或数据报的Unix域套接字。

  2. 发送进程通过调用返回描述符的任一Unix函数打开一个描述符,这些函数的例子有open、pipe、mkfifo、socket和accpet。

  3. 发送进程创建一个msghdr结构,其中含有待传递的描述符。

  4. 接收进程调用recvmsg在来自步骤1的Unix域套接字上接收这个描述符。

 

描述符传递的例子

  图1-1展示了上述步骤(1):通过调用socketpair创建一个流管道后的mycat进程。我们以后以[0]和[1]标示socketpair返回的两个描述符。

图1-1 使用socketpair创建流管道后的mycat进程

  mycat进程接着调用fork,进程再调用exec执行openfile程序。父进程关闭[1]描述符,子进程关闭[0]描述符。图1-2展示如此处理后的结果。

图1-2 启动执行openfile程序后的mycat进程

  父进程必须给openfile传递三条信息:(1)待打开文件的路径名,(2)打开方式(只读、读写或只写),(3)流管道本进程端。

  下面是mycat程序,把一个文件复制到标准输出。

  如果把my_open调用换成open调用,这个简单的程序就只是把一个文件复制到标准输出。

  read_fd函数接收数据和一个描述符。

  下面是openfile程序。它取得三个必须传入的命令行参数,并调用通常的open函数。

  最后一个函数是write_fd函数。

 

6 接收发送者的凭证

  通过Unix域套接字作为辅助数据传递的另一种数据是用户凭证(user credential)。

#include <bits/socket.h>
/* User visible structure for SCM_CREDENTIALS message */
struct ucred
{
  pid_t pid;            /* PID of sending process.  */
  uid_t uid;            /* UID of sending process.  */
  gid_t gid;            /* GID of sending process.  */
};

例子

  该函数由子进程在父进程接受了一个新的客户连接并调用fork之后调用。

 

 

 

 

 

 

 

 

 

 

© 著作权归作者所有

共有 人打赏支持
thanatos_y
粉丝 7
博文 112
码字总数 315059
作品 0
成都
程序员
0-Linux 网络编程学习笔记导航

学习交流群: Linux 学习交流群 610441700 说明:本系列文章并不能取代 《UNP》这本旷世之作,文章中难免有错误与不足之处,希望读者们遇到有疑问的地方可以加群互相交流,共同进步。写这一系...

q1007729991
2017/04/04
0
0
所看书籍记录

《程序员教程(第三版)》 《深入理解计算机系统》 《程序员的自我修养--链接、装载与库》(两遍) 《编译原理(龙书)》 《现代操作系统(第三版)》 《图解网络硬件》 《图解TCP/IP》 《数据...

thanatos_y
2016/03/14
62
0
Linux网络编程必看书籍推荐

首先要说讲述TCP/IP的书很多,其中有3泰书很全。 分别是《TCP/IP详解》三卷本,《用TCP/IP进行网际互连》三卷本,《TCP/IP指南》+《IPv6》四卷本 其中TCP/IP详解的作者还写了另外2本经典著作...

晨曦之光
2012/03/09
3.6K
0
Linux网络编程必看书籍推荐

首先要说讲述TCP/IP的书很多,其中有3泰书很全。 分别是《TCP/IP详解》三卷本,《用TCP/IP进行网际互连》三卷本,《TCP/IP指南》+《IPv6》四卷本 其中TCP/IP详解的作者还写了另外2本经典著作...

晨曦之光
2012/03/09
221
0
我的网络开发之旅——socket编程

上一篇文章《TCP/IP协议分析》讲述了自己是如何和网络领域的开发扯上关系的。正如从招聘网站上抽出的几个关键词“TCP/IP, Socket, 多线程”可见,协议分析并不是网络开发的主流,通常我们所说...

yaocoder
2014/09/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

腾讯三大运维开源项目齐聚“OSCAR开源先锋日”

10月20日,腾讯开源三大运维开源项目——TARS、蓝鲸和织云Metis首次集结,参与了由中国信息通信研究院主办、云计算标准与开源推进委员会承办的 “OSCAR开源先锋日”。会上,腾讯开源团队与前...

腾讯开源
17分钟前
0
0
JAVA并发-从缓存一致性说volatile 讲的很好

学过计算机组成原理的一定知道,为了解决内存速度跟不上CPU速度这个问题,在CPU的设计中加入了缓存机制,缓存的速度介于CPU和主存之间。在进行运算的时候,CPU将需要的数据映射一份在缓存中,...

码代码的小司机
35分钟前
0
0
IDEA 调试功能

1.设置断点 选定要设置断点的代码行,在行号的区域后面单击鼠标左键即可。 2.开启调试会话 点击红色箭头指向的小虫子,开始进入调试。 IDE下方出现Debug视图,红色的箭头指向的是现在调试程序...

狼王黄师傅
42分钟前
0
0
Java面试170题

1、面向对象的特征有哪些方面? 2、访问修饰符public,private,protected,以及不写(默认)时的区别? 3、String 是最基本的数据类型吗? 4、float f=3.4;是否正确? 5、short s1 = 1; s1 = ...

lanyu96
48分钟前
0
0
优雅的写出类

前言 虽然现在已经是ES6的时代,但是,还是有必要了解下ES5是怎么写一个类的。 本文详述JavaScript面向对象编程中的类写法,并分步骤讲述如何写出优雅的类。 一、例子 例子为一个轻提示组件T...

peakedness丶
53分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部