应先用is_resource($var)确认是资源,再用get_resource_type($var)区分"socket"或"stream"类型,因socket_create()返回"socket"而fsockopen()返回"stream",二者不兼容且需匹配对应操作函数。

用 is_resource() 判断变量是否为 Socket 资源
PHP 中 Socket 操作返回的是资源(resource)类型,不是对象也不是标量,所以不能用 is_object() 或 is_int() 来判断。最直接可靠的方式是先确认它是不是资源,再进一步确认资源类型:
-
is_resource($var)返回true仅说明它是某种资源,但不保证是 socket - 必须配合
get_resource_type($var)二次验证,因为文件句柄、cURL 句柄、MySQL 连接等也都是 resource - Socket 资源的类型名通常是
"stream"(如fsockopen()创建的),但socket_create()创建的是"socket"—— 注意这个关键区别
socket_create() 和 fsockopen() 的资源类型不同
这是最容易混淆的点:两种常见创建方式产生的资源类型不一致,导致检测逻辑不能一概而论:
-
socket_create(AF_INET, SOCK_STREAM, SOL_TCP)→get_resource_type()返回"socket" -
fsockopen("127.0.0.1", 80)→get_resource_type()返回"stream"(哪怕你后续用stream_socket_enable_crypto()) - 因此,只检查
get_resource_type() === "socket"会漏掉大量实际可用的 socket-like 流资源 - 若业务需要统一处理“可读写网络连接”,建议优先用
is_resource($var) && gettype($var) === "resource" && (get_resource_type($var) === "socket" || get_resource_type($var) === "stream"),再加stream_get_meta_data($var)看timed_out/eof等状态佐证
避免用 gettype() 直接判断
gettype($var) 对所有资源都返回 "resource",完全无法区分 socket、file、curl 等类型,纯属无效判断:
- 例如:
gettype(fopen("/tmp/a", "r"))和gettype(socket_create(...))都返回"resource" - 试图靠
gettype()+ 类型字符串匹配来识别 socket 是徒劳的 - 真正有用的只有
get_resource_type(),且必须结合创建上下文理解其含义
检测前务必确认资源未被关闭
已关闭的 socket 资源在 PHP 8+ 中仍可能通过 is_resource() 检测(表现为“伪有效”),但后续调用 socket_write() 或 fwrite() 会失败:
立即学习“PHP免费学习笔记(深入)”;
- 关闭后调用
get_resource_type()可能触发警告或返回空字符串,行为不稳定 - 安全做法是:检测前先用
is_resource($var) && !feof($var)(对 stream)或socket_get_option($var, SOL_SOCKET, SO_ERROR) !== false(对 socket)做存活验证 - 更稳妥的是封装成函数,例如:
function is_valid_socket($var): bool { if (!is_resource($var)) return false; $type = get_resource_type($var); if ($type === "socket") return socket_get_option($var, SOL_SOCKET, SO_ERROR) !== false; if ($type === "stream") return !feof($var) && @stream_get_meta_data($var)['unread_bytes'] !== null; return false; }
fsockopen() 返回值当成严格意义上的 “socket resource” 去调用 socket_*() 函数——它们根本不兼容。类型检测只是第一步,后续操作必须和创建方式严格对应。











