使用 Nim 语言和使用 C 语言, 调用系统 POSIX 接口传递文件描述符的对比
进程组之间传递文件描述符, 是多进程服务器共享套接字常用的方式. 基于此方式, 可以提供 round-robin , 使每个服务器获得平衡的负载.
Nim 和 C 语言调用相同的 POSIX 接口的编程方式如下, (事实上, Nim 是调用的 C POSIX 接口)
Nim
import posix
proc CMSG_LEN(length: cuint): cint {.importc, header: "<sys/socket.h>".}
proc socketpair(fds: var array[0..1, cint]): int {.inline.} =
result = socketpair(AF_UNIX, SOCK_STREAM, 0, fds)
var
pipeFds: array[0 .. 1, cint]
sockFds: array[0 .. 1, cint]
assert socketpair(pipeFds) == 0
assert socketpair(sockFds) == 0
####################### send model ###########################
var
sfd = pipeFds[0].SocketHandle()
sDataBuff = ['\0']
sIov = [TIOVec(iov_base: sDataBuff[0].addr(), iov_len: 1)]
sCmsglen = CMSG_LEN(sizeof(SocketHandle).cuint()) # 20
sCmsg = createU(Tcmsghdr, sCmsglen)
sMsg = Tmsghdr(msg_name: nil,
msg_namelen: 0,
msg_iov: sIov[0].addr(),
msg_iovlen: 1,
msg_control: sCmsg,
msg_controllen: sCmsglen.Socklen())
sCmsg.cmsg_len = sCmsglen.Socklen()
sCmsg.cmsg_level = SOL_SOCKET
sCmsg.cmsg_type = SCM_RIGHTS
(cast[ptr int](CMSG_DATA(sCmsg)))[] = sockFds[0]
assert sfd.sendmsg(sMsg.addr(), 0) == 1
free(sCmsg)
####################### recv model ###########################
var
rfd = pipeFds[1].SocketHandle()
rDataBuff = ['\0']
rIov = [TIOVec(iov_base: rDataBuff[0].addr(), iov_len: 1)]
rCmsglen = CMSG_LEN(sizeof(SocketHandle).cuint()) # 20
rCmsg = createU(Tcmsghdr, rCmsglen)
rMsg = Tmsghdr(msg_name: nil,
msg_namelen: 0,
msg_iov: rIov[0].addr(),
msg_iovlen: 1,
msg_control: rCmsg,
msg_controllen: rCmsglen.Socklen())
assert rfd.recvmsg(rMsg.addr(), 0) == 1
assert rCmsg.cmsg_len == rCmsglen.Socklen()
assert rCmsg.cmsg_level == SOL_SOCKET
assert rCmsg.cmsg_type == SCM_RIGHTS
echo((cast[ptr int](CMSG_DATA(rCmsg)))[])
free(rCmsg)
C
#include <sys/socket.h>
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
int main(int argc, char **argv) {
int pipeFds[1];
int sockFds[1];
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, pipeFds) == 0);
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sockFds) == 0);
/********************* send model *********************/
struct msghdr sMsg;
struct iovec sIov[1];
char sDataBuff[1] = "";
int sCmsglen = CMSG_LEN(sizeof(int)); // 20
struct cmsghdr *sCmsg = malloc(sCmsglen);
sIov[0].iov_base = sDataBuff;
sIov[0].iov_len = 1;
sMsg.msg_name = NULL;
sMsg.msg_namelen = 0;
sMsg.msg_iov = sIov;
sMsg.msg_iovlen = 1;
sMsg.msg_control = sCmsg;
sMsg.msg_controllen = sCmsglen; // 20
sCmsg->cmsg_len = sCmsglen; // 20
sCmsg->cmsg_level = SOL_SOCKET;
sCmsg->cmsg_type = SCM_RIGHTS;
*((int *)(CMSG_DATA(sCmsg))) = sockFds[0];
assert(sendmsg(pipeFds[0], &sMsg, 0) == 1);
free(sCmsg);
/********************* recv model *********************/
struct msghdr rMsg;
struct iovec rIov[1];
char rDataBuff[1] = "";
int rCmsglen = CMSG_LEN(sizeof(int)); // 20
struct cmsghdr *rCmsg = malloc(rCmsglen);
rIov[0].iov_base = rDataBuff;
rIov[0].iov_len = 1;
rMsg.msg_name = NULL;
rMsg.msg_namelen = 0;
rMsg.msg_iov = rIov;
rMsg.msg_iovlen = 1;
rMsg.msg_control = rCmsg;
rMsg.msg_controllen = rCmsglen; // 20
assert(recvmsg(pipeFds[1], &rMsg, 0) == 1);
assert(rCmsg->cmsg_len == rCmsglen);
assert(rCmsg->cmsg_level == SOL_SOCKET);
assert(rCmsg->cmsg_type == SCM_RIGHTS);
printf("%d\n", *((int *)(CMSG_DATA(rCmsg)))); // 7
free(rCmsg);
}
Nim lang 随笔
Good good study, and day day up.
14 声望
1 粉丝
推荐阅读
Redis 发布订阅模式:原理拆解并实现一个消息队列
“65 哥,如果你交了个漂亮小姐姐做女朋友,你会通过什么方式将这个消息广而告之给你的微信好友?““那不得拍点女朋友的美照 + 亲密照弄一个九宫格图文消息在朋友圈发布大肆宣传,暴击单身狗。”像这种 65 哥通过朋...
码哥字节赞 6阅读 1.8k
C 程序眼中的 Unicode
去年写了一篇文章「在 C 程序中处理 UTF-8 字符串」,介绍了如何使用 GLib 提供的 UTF-8 字符串处理函数来实现基本的 UTF-8 文本处理。不过,GLib 是一个功能比较全面的 C 程序库,C 字符串处理仅仅是它的一个很...
garfileo赞 3阅读 5.8k评论 5
滚蛋吧,正则表达式!
你是不是也有这样的操作,比如你需要使用「电子邮箱正则表达式」,首先想到的就是直接百度上搜索一个,然后采用 CV 大法神奇地接入到你的代码中?
良许赞 3阅读 1.4k
程序员适合创业吗?
大家好,我是良许。从去年 12 月开始,我已经在视频号、抖音等主流视频平台上连续更新视频到现在,并得到了不错的评价。每个视频都花了很多时间精力用心制作,欢迎大家关注哦~考虑到有些小伙伴没有看过我的视频,...
良许赞 3阅读 1.2k
记一次使用gdb诊断gc问题全过程
上次解决了GC长耗时问题后,系统果然平稳了许多,这是之前的文章《GC耗时高,原因竟是服务流量小?》 然而,过了一段时间,我检查GC日志时,又发现了一个GC问题,如下: 从这个图中可以发现,我们GC有一些尖峰,...
扣钉日记赞 2阅读 1.1k
使用kubeasz部署高可用kubernetes集群
本实验采用kubeasz作为kubernetes环境部署工具,它是一个基于二进制方式部署和利用ansible-playbook实现自动化来快速部署高可用kubernetes集群的工具,详细介绍请查看kubeasz官方。本实验用到的所有虚拟机默认软...
李朝阳赞 4阅读 728
计算机如何表示整数
在计算机中,任何的数据都是用二进制: 0 和 1 来表示。整数也不例外。生活中的 10,在 8 个字节的整数中表示为 00001010。但是这样子只能表示正数和零。怎么表示负数呢?于是有了符号位的概念。在 8 个字节的整...
kang赞 2阅读 3.2k评论 7
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。