Unix Domain Socket的一些理解

1. unix域的数据报服务是否可靠

man unix 手册即可看到,unix domain socket 的数据报既不会丢失也不会乱序 (据我所知,在linux下的确是这样)。不过最新版本的内核,仍然又提供了一个保证次序的类型 “ kernel 2.6.4 SOCK_SEQPACKET ”。

2. STREAM 和 DGRAM 的主要区别

既然数据报不丢失也可靠,那不是和 STREAM 很类似么?我理解也确实是这样,而且我觉得 DGRAM 相对还要好一些,因为发送的数据可以带边界。二者另外的区别在于收发时的数据量不一样,基于 STREAM 的套接字,send 可以传入超过 SO_SNDBUF 长的数据,recv 时同 TCP 类似会存在数据粘连。

采用阻塞方式使用API,在unix domain socket 下调用 sendto 时,如果缓冲队列已满,会阻塞。而UDP因为不是可靠的,无法感知对端的情况,即使对端没有及时收取数据,基本上sendto都能立即返回成功(如果发端疯狂sendto就另当别论,因为过快地调用sendto在慢速网络的环境下,可能撑爆套接字的缓冲区,导致sendto阻塞)。

3. SO_SNDBUF 和 SO_REVBUF

对于 unix domain socket,设置 SO_SNDBUF 会影响 sendto 最大的报文长度,但是任何针对 SO_RCVBUF 的设置都是无效的 。实际上 unix domain socket 的数据报还是得将数据放入内核所申请的内存块里面,再由另一个进程通过 recvfrom 从内核读取,因此具体可以发送的数据报长度受限于内核的 slab 策略 。在 linux 平台下,早先版本(如 2.6.2)可发送最大数据报长度约为 128 k ,新版本的内核支持更大的长度。

4. 使用 DGRAM 时,缓冲队列的长度

有几个因素会影响缓冲队列的长度,一个是上面提到的 slab 策略,另一个则是系统的内核参数 /proc/sys/net/unix/max_dgram_qlen。缓冲队列长度是这二者共同决定的。

如 max_dgram_qlen 默认为 10,在数据报较小时(如1k),先挂起接收数据的进程后,仍可以 sendto 10 次并顺利返回;

但是如果数据报较大(如120k)时,就要看 slab “size-131072” 的 limit 了。

5. 使用 unix domain socket 进行进程间通信 vs 其他方式

  • 需要先确定操作系统类型,以及其所对应的最大 DGRAM 长度,如果有需要传送超过该长度的数据报,建议拆分成几个发送,接收后组装即可(不会乱序,个人觉得这样做比用 STREAM 再切包方便得多)
  • 同管道相比,unix 域的数据报不但可以维持数据的边界,还不会碰到在写入管道时的原子性问题。
  • 同共享内存相比,不能独立于进程缓存大量数据,但是却避免了同步互斥的考量。
  • 同普通 socket 相比,开销相对较小(不用计算报头),DGRAM 的报文长度可以大于 64k,不过不能像普通 socket 那样将进程切换到不同机器 。

参考资料:

http://www.cnblogs.com/skynet/archive/2010/12/04/1881236.html

http://hi.baidu.com/studyarea/blog/item/b007f4450a2a9e38879473ca.html

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据