3

我的目标是将套接字连接(一旦“握手”(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

)

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

socket_send(): supplied resource is not a valid Socket

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

我在这里尝试以某种不同的方式传递套接字吗?我错过了什么(除了显而易见的事情)。

4

1 回答 1

1
$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() 有效

于 2020-11-05T21:43:05.003 回答