该系统调用能创建一对已连接的UNIX族socket。
在Linux中,完全可以把这一对socket当成pipe返回的文件描述符一样使用,唯一的区别就是这一对文件描述符中的任何一个都可读和可写,函数原型如下:
socketpair函数参数说明:
第1个参数domain
,表示协议族,只能为AF_LOCAL
或者AF_UNIX
。
第2个参数type
,表示协议,可以是SOCK_STREAM
或者SOCK_DGRAM
。用SOCK_STREAM
建立的套接字对是管道流,与一般的管道相区别的是,套接字对建立的通道是双向的,即每一端都可以进行读写。
第3个参数protocol
,表示类型,只能为0。
第4个参数sv[2]是接收代表两个套接口的整数数组。每一个文件描述符代表一个套接口,并且与另一个并没有区别。
<code class="hljs ocaml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*socketpair1.c*/</span> #<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> <sys/types.h> #<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> <sys/socket.h> #<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> <stdlib.h> #<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">include</span> <stdio.h> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">int</span> main () { <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">int</span> fd[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]; <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">int</span> r = socketpair(AF_UNIX, SOCK_STREAM, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, fd); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (r < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){ perror( <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"socketpair()"</span> ); exit(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (fork()){ <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* 父进程 */</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">int</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; close(fd[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span> (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>){ sleep(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>); ++<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>; printf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"发送数据: %d\n"</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>); write(fd[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>], &<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>, sizeof(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>)); read(fd[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>], &<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>, sizeof(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>)); printf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"接收数据: %d\n"</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>); } }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>{ <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*子进程*/</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">int</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>; close(fd[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>){ read(fd[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>], &<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>, sizeof(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>)); ++<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>; write(fd[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>], &<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>, sizeof(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">val</span>)); } } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li></ul>
分析程序:一开始由socketpair
创建一个套接字对,父进程关闭fd[1],子进程关闭fd[0],父进程sleep(1)
让子进程先执行,子进程read(fd[1], &val, sizeof(val))
阻塞,然后父进程write(fd[0]..)
发送数据,子进程接收数据处理后再发送给父进程数据write(fd[1]..)
,父进程读取数据,打印输出。(注意:socketpair产生的套接字对实现全双工通信)
sendmsg, recvmsg , send三个函数的头文件:
sendmsg函数
定义函数
参数s:为已建立好连线的socket, 如果利用UDP协议则不需经过连线操作.
参数msg:指向欲连线的数据结构内容, 参数flags 一般默认为0, 详细描述请参考send().
返回值:成功返回发送的字节数,出错返回-1
函数说明:recvmsg()用来接收远程主机经指定的socket 传来的数据.
参数s 为已建立好连线的socket, 如果利用UDP 协议则不需经过连线操作.
参数msg 指向欲连线的数据结构内容,
参数flags 一般设0, 详细描述请参考send().
返回值:成功则返回接收到的字符数, 失败则返回-1, 错误原因存于errno 中.
结构msghdr
定义如下:
错误代码:
msg_control
结构
控制信息头部本身由下面的C结构定义:
<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">成员 描述 cmsg_len 附属数据的字节计数,这包含结构头的尺寸。这个值是由CMSG_LEN()宏计算的。 cmsg_level 这个值表明了原始的协议级别(例如,SOL_SOCKET)。 cmsg_<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">type</span> 这个值表明了控制信息类型(例如,SCM_RIGHTS)。 cmsg_data 这个成员并不实际存在,用来指明实际的额外附属数据所在的位置。</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
用sendmsg来传递数据程序实例
<code class="hljs ruby has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">yu<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@ubuntu</span><span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:~/Linux/</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">217</span>/pro_pool/socketpair<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$ </span>gcc -o sendmsg sendmsg.c yu<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@ubuntu</span><span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:~/Linux/</span><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">217</span>/pro_pool/socketpair<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$ </span>./sendmsg 开始发送数据: 发送的数据为<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span> it is a test 发送成功! 接收成功! 收到数据为<span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:</span> it is a test</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>
程序分析:由套接字sock[1]发数据到本地主机,由套接字sock[0]接收发送过来的数据。