是否可以通过socket_sendmsgsendmsg将TCP套接字资源传递给AF_UNIX本地套接字,如果可以的话,如何

问题描述

我的目标是将套接字连接(一次“握手”(http升级)和“已认证”(我自己的函数,使用我提供的详细信息对我的数​​据库进行挑战)传递给另一个PHP脚本进程(不分叉) ),以便可以将其添加到自己的套接字资源“经过身份验证的客户端”数组中并接管连接。通过sendmsg的PHP包装器发送后(socket_sendmsg-谁的PHP文档不准确,因此我主要关注的是试图在c中执行相同操作的人)

如果我发送:

socket_sendmsg($hsSocket,["iov" => [json_encode(array('action'=>'add','uID'=>$messageObj->uID,'uDatID'=>$messageObj->uDatID,'sessID'=>$messageObj->sessID))],"control" => [["level" => SOL_SOCKET,"type" => SCM_RIGHTS,"data" => [$authlogfd]]]],0);

正在发送打开的日志文件文件描述符(如果我这样做的话)(在该resourceArray上的socket_select之后):

    if(socket_recvmsg($arrayOfSocketResources,$hsSocketData,MSG_DONTWAIT)){
                printf("SS:HS: got recvmsg control data\n");
                print_r($hsSocketData);
                if(isset($hsSocketData['control'][0]['data'][0])){
                $newlogfd=$hsSocketData['control'][0]['data'][0];   
                $msg=json_decode($hsSocketData['iov'][0],true);
                if(isset($msg['action'])&&$msg['action']=='add'){
                $sendmsg=PHP_EOL."from second script".PHP_EOL;
                fwrite($newlogfd,$sendmsg,strlen($sendmsg));
                printf("SS:HS: got descriptor %s action:%s uID:%s uDatID:%s sessID:%s\n",$newlogfd,$msg['action'],$msg['uID'],$msg['uDatID'],$msg['sessID']);
                }

然后,我在日志中看到消息“来自第二个脚本”(因此,即使关闭传递者之后,我也可以写出传递给它的文件描述符(对文件描述附加的每个进程都有计数)递增))。如果我从传递者(而不是日志文件描述符)发送该消息,这对STDOUT也有效。

当我更改为发送经过身份验证的tcp套接字客户端资源之一时,如果我转储,它将显示资源ID:

          Array(
[name] => 
[control] => Array
    ([0] => Array
            (
                [level] => 1
                [type] => 1
                [data] => Array
                    (
                        [0] => Resource id #12
                    )

            )

    )

[iov] => Array
    (
        [0] => {"action":"add","uID":"816-2554846393-11","uDatID":"fe1eba892f2144b3c9ce49f79c7a8386","sessID":"9mpr38o5nrmqke0mfejvn3801l"}
    )

[flags] => 0

问题是,当我尝试使用传递的套接字资源“获得的资源ID#12”时

socket_send(): supplied resource is not a valid Socket

在其读取资源数组中添加了“ Resource id#12”的socket_select也很烦人,抱怨它无效。

我要通过某种不同的方式传递套接字吗?我想念的东西(除了明显的东西)。

解决方法

$r = socket_sendmsg($authSocket,["iov" => [json_encode(array('uID'=>$socketMYSQL->unboxID($messageObj->uID),'uDatID'=>$messageObj->uDatID,'sessID'=>$messageObj->sessID))],"control" => [["level" => SOL_SOCKET,"type" => SCM_RIGHTS,"data" => [socket_export_stream($newSocketArrayResource),STDOUT]]]],0);

socket_export_stream()是我现在收到的fd上的var_dump时我所缺少的魔力(我认为它将套接字封装在流对象中)

resource(13) of type (Socket)

代替

resource(13) of type (stream)

和socket_getpeername()有效