文档章节

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

thanatos_y
 thanatos_y
发布于 2016/04/20 16:27
字数 1903
阅读 51
收藏 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 网络编程修炼指南——内功心法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q1007729991/article/details/69091877 学习交流群: Linux 学习交流群 610441700 说明:本系列文章并不能取代...

--Allen--
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
300
0
Linux网络编程必看书籍推荐

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

晨曦之光
2012/03/09
3.8K
0
我的网络开发之旅——TCP/IP协议分析

之前在当地的一期技术沙龙做了一个《网络开发那些事》的技术分享,讲述了自己职业生涯从事的与网络相关的开发工作。在接触这类开发之前一直在从事业务系统或者单机系统的开发,说真的那时感觉...

yaocoder
2014/09/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 你一口我一口多咬一口是小狗

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @达尔文 :分享Roy Orbison的单曲《She's a Mystery to Me》 《She's a Mystery to Me》- Roy Orbison 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
今天
56
4
Spring源码学习笔记-1-Resource

打算补下基础,学习下Spring源码,参考书籍是《Spring源码深度解析》,使用版本是Spring 3.2.x,本来想试图用脑图记录的,发现代码部分不好贴,还是作罢,这里只大略记录下想法,不写太细了 ...

zypy333
今天
12
0
RestClientUtil和ConfigRestClientUtil区别说明

RestClientUtil directly executes the DSL defined in the code. ConfigRestClientUtil gets the DSL defined in the configuration file by the DSL name and executes it. RestClientUtil......

bboss
今天
20
0

中国龙-扬科
昨天
4
0
Linux系统设置全局的默认网络代理

更改全局配置文件/etc/profile all_proxy="all_proxy=socks://rahowviahva.ml:80/"ftp_proxy="ftp_proxy=http://rahowviahva.ml:80/"http_proxy="http_proxy=http://rahowviahva.ml:80/"......

临江仙卜算子
昨天
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部