文档章节

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

thanatos_y
 thanatos_y
发布于 2016/04/20 16:27
字数 1903
阅读 42
收藏 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

没有更多内容

加载失败,请刷新页面

加载更多

下一页

kernel version does not match DSO version

错误信息: kernel version 384.11 does not match DSO version 384.130.0 原因是: cuda driver版本太低,不匹配DSO 简单有效的修复方法,升级nvidia driver, 步骤如下: 1. google seach ...

刘小米
今天
0
0
maven坐标和依赖

一、maven坐标详解 <groupId>com.fgt.club</groupId><artifactId>club-common-service-facade</artifactId><version>3.0.0</version><packaging>jar</packaging> maven的坐标元素说......

老韭菜
今天
1
0
springmvc-servlet.xml配置表功能解释

问:<?xml version="1.0" encoding="UTF-8" ?> 答: xml version="1.0"表示是此xml文件的版本是1.0 encoding="UTF-8"表示此文件的编码方式是UTF-8 问:<!DOCTYPE beans PUBLIC "-//SPRING//......

隐士族隐逸
今天
1
0
基于TP5的微信的公众号获取登录用户信息

之前讲过微信的公众号自动登录的菜单配置,这次记录一下在TP5项目中获取自动登录的用户信息并存到数据库的操作 基本的流程为:微信设置自动登录的菜单—>访问的URL指定的函数里获取用户信息—...

月夜中徘徊
今天
0
0
youTrack

package jetbrains.teamsys.license.runtime; 计算lis package jetbrains.ring.license.reader; 验证lis 安装后先不要生成lis,要把相关文件进行替换 ring-license-checker-1.0.41.jar char......

max佩恩
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部