关于什么是UNIX域套接字可以参考:http://www.cnblogs.com/xcywt/p/8185597.html
这里主要介绍非命名的UNIX域套接字的用法。

1.socketpair函数
先看man手册:

SYNOPSIS
       #include <sys/types.h>          /* See NOTES */
       #include <sys/socket.h>

int socketpair(int domain, int type, int protocol, int sv[2]);

DESCRIPTION
       The  socketpair()  call creates an unnamed pair of connected sockets in
       the specified domain, of the specified type, and using  the  optionally
       specified  protocol.   For  further  details  of  these  arguments, see
       socket(2).

The descriptors used in referencing the new  sockets  are  returned  in
       sv[0] and sv[1].  The two sockets are indistinguishable.

RETURN VALUE
       On  success,  zero is returned.  On error, -1 is returned, and errno is
       set appropriately.

功能:创建一个全双工的流管道
参数:
domain:协议家族,为AF_LOCAL或AF_UNIX
type:套接字类型。可以是SOCK_STREAM或者SOCK_DGRAM。这两种都是可靠的
protocol:协议类型。为0
sv:返回套接字对,这个是输出参数。返回的两个描述符都是可读可写的。
返回值:成功返回0,失败返回-1.
补充:pipe创建的匿名管道的半双工的,pipefd[0]用于读,pipefd[1]用于写。
注意:由于创建的每个套接字都是没有名字的,这就意味着无关进程不能使用它们。

2.一个简单的例子:
父进程给子进程发送一个数据给子进程,子进程收到数据后最数据进行加一操作,再发回给父进程。
先上自己的一个头文件:
comm.h

#ifndef __COMM_H__
#define __COMM_H__ #include<errno.h>
#include<stdlib.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() #endif // __COMM_H__

再上主程序:

#include<stdio.h>
#include<unistd.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h> #include"comm.h" int main()
{
int sockfds[];
if(socketpair(PF_UNIX, SOCK_STREAM, , sockfds) < )
ERR_EXIT("sockerpair"); pid_t pid;
pid = fork();
if(pid < )
ERR_EXIT("fork");
else if(pid > )
{
int val = ;
close(sockfds[]);
while()
{
++val;
printf("Sending data: %d\n", val);
write(sockfds[], &val, sizeof(val));
read(sockfds[], &val, sizeof(val));
printf(" Recv data: %d\n", val);
sleep();
}
}
else
{
close(sockfds[]);
int val;
while()
{
read(sockfds[], &val, sizeof(val));
++val;
write(sockfds[], &val, sizeof(val));
}
}
return ;
}

运行:

xcy@xcy-virtual-machine:~/test/sock14_socketpair$ ./sockpair
Sending data:
Recv data:
Sending data:
Recv data:
Sending data:
Recv data:
Sending data:
Recv data:
Sending data:
Recv data:
Sending data:
Recv data:
Sending data:
Recv data:

3.UNIX域传递文件描述符

需要用到sendmsg和recvmsg函数:

#include <sys/types.h>
       #include <sys/socket.h>
       ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
       ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

主要封装了两个函数,recv_fd和send_fd。
直接上代码:

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/socket.h>
#include"comm.h" // 这个文件见上面的例子有 void send_fd(int sock_fd, int send_fd)
{
int ret = ;
struct msghdr msg;
struct cmsghdr *p_cmsg;
struct iovec vec;
char cmsgbuf[CMSG_SPACE(sizeof(send_fd))];
int *p_fds;
char sendchar = ;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf); p_cmsg = CMSG_FIRSTHDR(&msg);
p_cmsg->cmsg_level = SOL_SOCKET;
p_cmsg->cmsg_type = SCM_RIGHTS;
p_cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd));
p_fds = (int*)CMSG_DATA(p_cmsg);
*p_fds = send_fd; msg.msg_name = NULL;
msg.msg_namelen = ;
msg.msg_iov = &vec;
msg.msg_iovlen = ;
msg.msg_flags = ; vec.iov_base = &sendchar;
vec.iov_len = sizeof(sendchar);
ret = sendmsg(sock_fd, &msg, );
if(ret < )
ERR_EXIT("sendmsg");
}
int recv_fd(const int sock_fd)
{
int ret = ;
struct msghdr msg;
char recvchar;
struct iovec vec;
int recv_fd;
char cmsgbuf[CMSG_SPACE(sizeof(recv_fd))];
struct cmsghdr *p_cmsg;
int *p_fd = NULL;
vec.iov_base = &recvchar;
vec.iov_len = sizeof(recvchar);
msg.msg_name = NULL;
msg.msg_namelen = ;
msg.msg_iov = &vec;
msg.msg_iovlen = ;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
msg.msg_flags = ; p_fd = (int *)CMSG_DATA(CMSG_FIRSTHDR(&msg));
*p_fd = -;
ret = recvmsg(sock_fd, &msg, );
if(ret < )
ERR_EXIT("recvmsg"); p_cmsg = CMSG_FIRSTHDR(&msg);
if(p_cmsg == NULL)
ERR_EXIT("no passed fd"); p_fd = (int*)CMSG_DATA(p_cmsg);
recv_fd = *p_fd;
if(recv_fd == -)
ERR_EXIT("no passed fd"); return recv_fd;
} #define OPEN_FILE "test.txt" int main()
{
int sockfds[];
if(socketpair(PF_UNIX, SOCK_STREAM, , sockfds) < )
ERR_EXIT("socketpair");
pid_t pid = fork();
if(pid < )
ERR_EXIT("fork");
else if(pid > )
{
close(sockfds[]);
char buf[] = {};
int fd = recv_fd(sockfds[]);
read(fd, buf, sizeof(buf));
printf("Get Data:\n%s", buf);
}
else
{
close(sockfds[]);
int fd = open(OPEN_FILE, O_RDONLY);
if(fd < )
ERR_EXIT("open");
send_fd(sockfds[], fd);
}
return ;
}

分析:子进程中打开一个文件描述符,然后通过send_fd发送给主进程,主进程通过recv_fd接收这个文件描述符。再通过这个文件描述符读取文件的内容。
运行,需要先创建一个test.txt文件,再运行:

xcy@xcy-virtual-machine:~/test/sock14_socketpair$ ./sendfd
Get Data:
I am xiaochongyong
How are you?
I'm fine. And you!
xcy@xcy-virtual-machine:~/test/sock14_socketpair$

补充:
1)虽然文件描述符是一个整形数字,但是单纯发一个数字过去是没有用的。
2)普通的TCP UDP套接字是不能传递文件描述符的

UNIX域协议(无名套接字)的更多相关文章

  1. UNIX域协议(命名套接字)

    这里主要介绍命名UNIX域套接字 1.什么是UNIX域套接字Unix域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务通信的一种方式.是进程间通信(IPC)的一种方式.它提供了两类套接字:字 ...

  2. Socket编程实践(13) --UNIX域协议

    UNIX域协议 UNIX域套接字与TCP相比, 在同一台主机上, UNIX域套接字更有效率, 几乎是TCP的两倍(由于UNIX域套接字不需要经过网络协议栈,不需要打包/拆包,计算校验和,维护序号和应答 ...

  3. unix网络编程——TCP套接字编程

    TCP客户端和服务端所需的基本套接字.服务器先启动,之后的某个时刻客户端启动并试图连接到服务器.之后客户端向服务器发送请求,服务器处理请求,并给客户端一个响应.该过程一直持续下去,直到客户端关闭,给服 ...

  4. UNIX网络编程读书笔记:UNIX域协议

    概述 UNIX域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方法,所用API与在不同主机上执行客户/服务器通信所用的API(套接口API)相同.UNIX域协议可视为进程间通信 ...

  5. UNP学习笔记(第十五章 UNIX域协议)

    UNIX域协议是在单个主机上执行客户/服务器通信的一种方法 使用UNIX域套接字有以下3个理由: 1.UNIX域套接字往往比通信两端位于同一个主机的TCP套接字快出一倍 2.UNIX域套接字可用于在同 ...

  6. UNP学习 Unix域协议

    Unix域协议并不是一个实际的协议族,它只是在同一台主机上进行客户-服务器通信时,使用与在不同主机上的客户和服务器间通信时相同的API的一种方法. 当客户和服务器在同一台主机上时,Unix域协议是这套 ...

  7. 《Unix 网络编程》15:Unix 域协议

    Unix 域协议 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ 本 ...

  8. UNIX网络编程——原始套接字的魔力【续】

    如何从链路层直接发送数据帧 上一篇里面提到的是从链路层"收发"数据,该篇是从链路层发送数据帧. 上一节我们主要研究了如何从链路层直接接收数据帧,可以通过bind函数来将原始套接字绑 ...

  9. 网络编程----socket介绍、基于tcp协议的套接字实现、基于udp协议的套接字实现

    一.客户端/服务器架构(C/S架构)                                                即C/S架构,包括: 1.硬件C/S架构(打印机) 2.软件C/S架 ...

  10. 基于udp协议的套接字及udp协议粘包问题

    udp协议的套接字 udp协议传输  服务端和客户端没有建立连接一说. import socket # 总结一下基础工作流程:服务端生成套接字并绑定ip_port,进入数据传输循环,服务端接受客户端发 ...

随机推荐

  1. 离开Visual Studio C#的编译(你不知道的C#)

    很多人一开始学习.net 第一天必定是安装Visual studio 或者很多关于C#学习的书上第一章节必定是告诉你要你下载一个vs 其实没有vs未必就不能开发了,只是可能说vs给我的开发带来了很多的 ...

  2. Netty与传统Server对比

    前言 本文旨在介绍传统Socket服务端与NIO服务端的差异. 以餐厅服务员简单举例,每个客人对应一个请求. 传统Socket / OIO public class OioServer { @Supp ...

  3. SqlParameter 用法总结

    作用 解决恶意的T-sql语句攻击第一种 //传入参数 string ProductGroupCode, string Ismaintain, int HierarchyID, string BOMN ...

  4. always中的敏感变量

    always语句下如果有判断语句if,那么if语句中的条件必须有always中的敏感变量. 否则错误提示为:Error (10200): Verilog HDL Conditional Stateme ...

  5. 基于Accord.Audio和百度语言识别

    ---恢复内容开始--- 目标需求 使用录音形式,模拟微信语音聊天.按住录音,松开发送语音,并完成语音识别. ps:百度的语言识别有60秒长度限制,需要自己做好控制. 实现方案 采用C# winfor ...

  6. 解析XML文件之使用SAM解析器

    XML是一种常见的传输数据方式,所以在开发中,我们会遇到对XML文件进行解析的时候,本篇主要介绍使用SAM解析器,对XML文件进行解析. SAX解析器的长处是显而易见的.那就是SAX并不须要将全部的文 ...

  7. redis缓存的安装和配置

    ubantu16.04环境下安装 下载安装,依次执行命令; # 从官方网站下载安装包,注意,当前在哪个目录下执行命令,下载的包将在哪个目录下 $ wget http://download.redis. ...

  8. ABP入门系列(12)——如何升级Abp并调试源码

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1. 升级Abp 本系列教程是基于Abp V1.0版本,现在Abp版本已经升级至V1.4.2(截至 ...

  9. androidstudio连接SCM Manager上的Git库

    1.在SCM Manager里创建一个Git库 在androidstudio里选中从版本控制里导入 输入git库的地址,接下来一路点击下一步 完成之后会可以在工程里创建文件或者从别的地方把完整项目拷贝 ...

  10. 利用AndroidStudio开发java工程

    1.新建一个project,或者如果你已经有project的话,那就直接新建一个module.注意选择Java library,然后下一步. 2.输入module的一些信息.点击finish.(在创建 ...