执行workerman status命令后,会导致设置的socket超时时长失效

刘看山

执行workerman status命令后,会导致设置的socket超时时长失效

RT,我是在thinkphp6中使用wokerman执行异步任务,主要是发送TCP请求给三方接口,因为三方处理的比较慢,所以设置了1个小时的超时时间,也就是代码会在socket_read() 这里等待1小时,但是当我运行workermanstatus的命令后,会导致socket_read这里立即返回,导致我设置的超时时间就失效,请问这是怎么回事,该如何解决
我感觉和这个问题很像,https://www.workerman.net/q/2367
因为需要定期查看进程状态,我该如何避免这种情况发生

        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        //如果运行workerman status 这里设置的超时时长就失效了
        socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 3600, "usec" => 0));
        socket_set_block($socket);
        //self::log("tcp request:0001" );
        if (@socket_connect($socket, self::getHost(), $port) === false) {

            // 创建连接
            socket_close($socket);

            $message = sprintf("create socket error:%s", socket_strerror(socket_last_error()));
            throw new TcpException($message);

        }
        //self::log("tcp request:0002" );
        $length = strlen($msg);
        //self::log("tcp request:0003" );
        $result = @socket_write($socket, $msg, $length);
        //self::log("tcp request:0004" );

        unset($msg);

        if (false === $result) {
            //self::log("tcp request error:0002" );
            socket_close($socket);
            $message = sprintf("write socket error:%s", socket_strerror(socket_last_error()));
            throw new TcpException($message);
        }

        $response = '';
        $tmp = '';
        $i = 0;
        // socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 3600, "usec" => 0));
        self::log('FeiDongAI TCP','socket_read Before');
        while ($tmp = @socket_read($socket, 2048, PHP_BINARY_READ)) {
            self::log('socket_read', $tmp . ' 序号' . $i++);
            if (empty($tmp)) {
                break;
            }
            $response .= $tmp;
        }
      self::log('socket_read while complete', $response);
        //      self::log('FeiDongAI TCP','socket_read Complete');
        socket_close($socket);

        if (empty($response)) {
            return $response;
        }
        //self::log($response);
        $response = json_decode(substr($response, 4), true);
        $response = empty($response) ? [] : $response;
        return $response;   //self::log("request content", $msg);
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 3600, "usec" => 0));
        socket_set_block($socket);
        //self::log("tcp request:0001" );
        if (@socket_connect($socket, self::getHost(), $port) === false) {

            // 创建连接
            socket_close($socket);

            $message = sprintf("create socket error:%s", socket_strerror(socket_last_error()));
            throw new TcpException($message);

        }
        //self::log("tcp request:0002" );
        $length = strlen($msg);
        //self::log("tcp request:0003" );
        $result = @socket_write($socket, $msg, $length);
        //self::log("tcp request:0004" );

        unset($msg);

        if (false === $result) {
            //self::log("tcp request error:0002" );
            socket_close($socket);
            $message = sprintf("write socket error:%s",socket_strerror(socket_last_error()));
            throw new TcpException($message);
        }

        $response = '';
        $tmp = '';
        while ($tmp = @socket_read($socket, 2048, PHP_BINARY_READ)) {
            if (empty($tmp)) {
                break;
            }
            $response .= $tmp;
        }
        socket_close($socket);

        if (empty($response)) {
            return $response;
        }
        $response = json_decode(substr($response, 4), true);
        $response = empty($response) ? [] : $response;
        return $response;
283 1 0
1个回答

walkor

这个属于网络编程的知识,status命令会触发信号,信号会打断socket_read调用,socket_read会立刻返回false。
解决这个问题需要自己加一个时间判断,代码类似

$timeout = 60;
$startTime = time();
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ['sec' => $timeout, 'usec' => 0]);
while (1) {
    $tmp = @socket_read($socket, 2048, PHP_BINARY_READ);
    if ($tmp === false) {
        $code = socket_last_error($socket);
        socket_clear_error($socket);
        if ($code !== 4) {
            break;
        }
        // socket被信号打断
        $leftTimeout = $timeout - (time() - $startTime);
        echo $leftTimeout,"\n";
        if ($timeout <= 0) {
            break;
        }
        socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ['sec' => $leftTimeout, 'usec' => 0]);
        continue;
    }
    if ($tmp === '') {
        break;
    }
    $response .= $tmp;
}
×
🔝