Nim 和 C 語言實現(xiàn) __ 套接字管道傳遞描述符

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);
}

union version

#include <sys/socket.h>
#include <stdio.h>
#include <assert.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] = "";
    struct cmsghdr *sCmsg;
    union {
        struct cmsghdr cm;
        char buff[CMSG_SPACE(sizeof(int))];           // 24
    } sFdBuff;
    
    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 = sFdBuff.buff;
    sMsg.msg_controllen = sizeof(sFdBuff.buff);         // 24

    sCmsg = CMSG_FIRSTHDR(&sMsg);
    sCmsg->cmsg_len = CMSG_LEN(sizeof(int));            // 20
    sCmsg->cmsg_level = SOL_SOCKET;
    sCmsg->cmsg_type = SCM_RIGHTS;
    *((int *)(CMSG_DATA(sCmsg))) = sockFds[0];

    assert(sendmsg(pipeFds[0], &sMsg, 0) == 1);

    /********************* recv model *********************/
    
    struct msghdr rMsg;
    struct iovec rIov[1];
    char rDataBuff[1] = "";
    struct cmsghdr *rCmsg;
    union {
        struct cmsghdr cm;
        char buff[CMSG_SPACE(sizeof(int))];             // 24
    } rFdBuff;

    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 = rFdBuff.buff;
    rMsg.msg_controllen = sizeof(rFdBuff.buff);         // 24

    assert(recvmsg(pipeFds[1], &rMsg, 0) == 1);

    rCmsg = CMSG_FIRSTHDR(&rMsg);

    assert(rCmsg->cmsg_len == CMSG_LEN(sizeof(int)));
    assert(rCmsg->cmsg_level == SOL_SOCKET);
    assert(rCmsg->cmsg_type == SCM_RIGHTS);
    printf("%d\n", *((int *)(CMSG_DATA(rCmsg))));       // 7
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末叔收,一起剝皮案震驚了整個濱河市剑鞍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖畦木,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異柠掂,居然都是意外死亡熊杨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門别垮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來便监,“玉大人,你說我怎么就攤上這事宰闰〔绻螅” “怎么了簿透?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長解藻。 經(jīng)常有香客問我老充,道長,這世上最難降的妖魔是什么螟左? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任啡浊,我火速辦了婚禮,結(jié)果婚禮上胶背,老公的妹妹穿的比我還像新娘巷嚣。我一直安慰自己,他們只是感情好钳吟,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布廷粒。 她就那樣靜靜地躺著,像睡著了一般红且。 火紅的嫁衣襯著肌膚如雪坝茎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天暇番,我揣著相機與錄音嗤放,去河邊找鬼。 笑死壁酬,一個胖子當(dāng)著我的面吹牛次酌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播舆乔,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼岳服,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蜕煌?” 一聲冷哼從身側(cè)響起派阱,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎斜纪,沒想到半個月后贫母,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡盒刚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年腺劣,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片因块。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡橘原,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情趾断,我是刑警寧澤拒名,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站芋酌,受9級特大地震影響增显,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脐帝,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一同云、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧堵腹,春花似錦炸站、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至荡含,卻和暖如春咒唆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背释液。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留装处,地道東北人误债。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像妄迁,于是被迫代替她去往敵國和親寝蹈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容