Unix domain socket 的一些小结

前端之家收集整理的这篇文章主要介绍了Unix domain socket 的一些小结前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

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

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


@H_502_4@@H_502_4@

2. STREAM 和 DGRAM 的主要区别@H_502_4@@H_502_4@@H_502_4@

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

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

3. SO_SNDBUF 和 SO_REVBUF@H_502_4@@H_502_4@@H_502_4@

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

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

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

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

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

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

· 需要先确定操作系统类型,以及其所对应的最大 DGRAM 长度,如果有需要传送超过该长度的数据报,建议拆分成几个发送,接收后组装即可(不会乱序,个人觉得这样做比用 STREAM 再切包方便得多)@H_502_4@@H_502_4@

· 同管道相比,unix 域的数据报不但可以维持数据的边界,还不会碰到在写入管道时的原子性问题。@H_502_4@@H_502_4@

· 同共享内存相比,不能独立于进程缓存大量数据,但是却避免了同步互斥的考量。@H_502_4@@H_502_4@

· 同普通 socket 相比,开销相对较小(不用计算报头),DGRAM 的报文长度可以大于 64k,不过不能像普通 socket 那样将进程切换到不同机器@H_502_4@@H_502_4@。@H_502_4@@H_502_4@

6. 其他@H_502_4@@H_502_4@@H_502_4@

其实在本机 IPC 时,同普通 socket 的 UDP 相比,unix domain socket 的数据报只不过是在收发时分别少计算了一下校验和而已,本机的 UDP 会走 lo 接口,不会进行 IP 分片,也不会真正跑到网卡的链路层上去(不会占用网卡硬件)@H_502_4@@H_502_4@。也就是说,在本机上使用普通的 socket UDP,只是多耗了一些 cpu(之所以说一些,是因为校验和的计算很简单),此外本机的 UDP 也可以保证数据不丢失、不乱序@H_502_4@@H_502_4@。@H_502_4@@H_502_4@

从我个人的经验来看,即便是高并发的网络服务器,单纯因为收发包造成的 cpu 占用其实并不算多(其中收包占用的 cpu 从 %si 可见一斑,因为收包需通过软中断实现的),倒是网卡带宽、磁盘IO、后台逻辑、内存使用等问题往往成为主要矛盾。@H_502_4@@H_502_4@

@H_502_4@所以,在没有长时缓存通信数据的需求时,可以考虑通过 UDP 来实现本地进程间 IPC,这样也便于切换机器。@H_502_4@@H_502_4@@H_502_4@(也不必去操心 unix domain socket 数据报的最大长度了,呵呵)对于较长的报文,可以切分成小的,再重新组装,不过这样做仅适用于本机通信,如果还要考虑以后迁移机器,那还是老老实实地 TCP 吧。@H_502_4@@H_502_4@(本地 TCP 耗用资源的情况不得而知,没有做过充分的测试,不过本地 TCP 自身的一些收发包操作一般也不构成瓶颈)@H_502_4@@H_502_4@@H_502_4@

---在 google 时查找到的其他资源也一并列在这里---@H_502_4@@H_502_4@

setsockopt 设置 SO_SNDBUF SO_RCVBUF 时的冗余分配:@H_502_4@

http://www.tux.org/lkml/
@H_502_4@

unix域套接字的使用:
@H_502_4@

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

猜你在找的Bash相关文章