如何让PHP Socket监听HL7消息仅固定时长并超时报错?
实现Socket监听10秒超时并抛出错误
当然可以实现这个需求!我们可以利用PHP Socket扩展的超时配置功能,给监听和读取操作设置10秒的超时时间,当超时发生时捕获错误并抛出异常。下面是修改后的完整代码,以及关键步骤的解释:
$address = '0.0.0.0'; $port = 5600; // 创建TCP流套接字 $sock = socket_create(AF_INET, SOCK_STREAM, 0); if (!$sock) { throw new Exception("创建套接字失败: " . socket_strerror(socket_last_error())); } // 设置套接字接收超时:10秒0微秒 $timeout = ['sec' => 10, 'usec' => 0]; if (!socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, $timeout)) { throw new Exception("设置超时失败: " . socket_strerror(socket_last_error())); } // 绑定地址和端口 $bind = socket_bind($sock, $address, $port); if (!$bind) { throw new Exception("绑定套接字失败: " . socket_strerror(socket_last_error())); } // 开始监听连接 if (!socket_listen($sock)) { throw new Exception("监听套接字失败: " . socket_strerror(socket_last_error())); } // 等待客户端连接(带10秒超时) $client = socket_accept($sock); if (!$client) { $errorCode = socket_last_error($sock); $errorMsg = socket_strerror($errorCode); // 判断是否为超时错误(错误码110对应ETIMEDOUT) if ($errorCode === 110) { throw new Exception("监听超时:10秒内无设备连接"); } else { throw new Exception("接受连接失败: " . $errorMsg); } } // 读取客户端消息(同样受之前设置的超时限制) $input = socket_read($client, 2024); if ($input === false) { $errorCode = socket_last_error($client); $errorMsg = socket_strerror($errorCode); if ($errorCode === 110) { throw new Exception("读取消息超时:10秒内无设备发送HL7消息"); } else { throw new Exception("读取消息失败: " . $errorMsg); } } // 处理HL7消息(原逻辑保留) $segs = explode("|", $input); // 关闭客户端套接字 socket_close($client); // 关闭监听套接字 socket_close($sock);
关键修改点说明:
- 设置超时选项:通过
socket_set_option()给套接字设置SO_RCVTIMEO选项,这个选项会同时约束后续的socket_accept()(等待连接)和socket_read()(读取消息)操作的超时时间。 - 精准错误判断:每次套接字操作后都检查返回值,失败时通过
socket_last_error()获取错误码,判断是否为超时错误(通用错误码110对应ETIMEDOUT),针对性抛出超时异常,其他错误则返回具体原因。 - 完善基础错误处理:补充了创建、绑定、监听等核心步骤的错误检查,避免因基础套接字操作失败导致无意义的阻塞。
注意:不同操作系统的错误码可能有细微差异,如果遇到超时判断不生效的情况,可以打印$errorCode值来确认当前系统的超时错误码。
内容的提问来源于stack exchange,提问作者user5349142
相关产品推荐
相关产品推荐

