php使用stream_socket_client发送异步请求

本文介绍如何使用PHP的stream_socket_client函数实现异步HTTP POST请求,通过实例详细讲解了header构造和数据发送过程,适合PHP开发者深入理解并发通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

php使用stream_socket_client发送异步请求

public function sockPost($host,$path,$params){
        $query =http_build_query($params);
//        $fp = fsockopen('ssl://'.$host, 443, $errno, $errstr, 60);
        $fp = stream_socket_client('ssl://'.$host.':443', $errno, $errstr, 60);
        $head = "POST ".$path."?".$query." HTTP/1.0\r\n";
        $head .= "Host: ".$host."\r\n";
        $head .= "Referer: https://".$host.$path."\r\n";
        $head .= "Content-type: application/x-www-form-urlencoded\r\n";
        $head .= "Content-Length: ".strlen(trim($query))."\r\n";
        $head .= "\r\n";
        $head .= trim($query)."\r\n";
        $write = fwrite($fp, $head);
        fclose($fp);
    }

欢迎交流指点!我的微信:

### 关于 `client_socket.recv()` 的解决方案 `client_socket.recv()` 方法通常用于接收来自网络连接的数据,默认情况下它是阻塞式的,这意味着程序会一直等待直到有数据到达。如果希望多次调用该函数来持续接收数据,则需要注意以下几个方面: #### 1. 循环处理接收逻辑 为了能够连续接收多个消息,可以将 `recv()` 放置在一个循环中不断读取数据,直到满足特定条件为止。例如,在客户端关闭之前保持接收状态。 ```python import socket def main(): tcp_client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) tcp_client_socket.connect(("127.0.0.1", 8000)) while True: send_data = input("请输入要发送的数据(输入 'exit' 结束):") if send_data.lower() == "exit": break tcp_client_socket.send(send_data.encode()) try: # 设置缓冲区大小并尝试接收更多数据 recv_data = b"" chunk_size = 1024 while True: data_chunk = tcp_client_socket.recv(chunk_size) # 接收数据 if not data_chunk: break recv_data += data_chunk # 将接收到的部分拼接到一起 print("服务器返回:", recv_data.decode()) except Exception as e: print(f"发生错误 {e}") tcp_client_socket.close() if __name__ == '__main__': main() ``` 上述代码通过一个无限循环实现了多轮通信功能[^1]。每次发送完数据后都会进入一个新的接收阶段,从而解决了单次接收的问题。 #### 2. 非阻塞模式下的应用 当需要更灵活地控制何时以及如何接收数据时,可考虑设置套接字为非阻塞模式,并结合异常捕获机制完成操作。这种方式特别适合异步场景或者高并发环境中的使用案例。 以下是基于引用[3]修改后的版本展示如何切换到非阻塞方式工作: ```python import socket def set_nonblocking(sock): sock.setblocking(False) def main(): tcp_client_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) set_nonblocking(tcp_client_socket) # 调整为非阻塞 try: tcp_client_socket.connect_ex(("127.0.0.1", 8000)) # 使用 connect_ex 来避免立即抛出异常 except BlockingIOError: pass # 正常忽略此错误因为是非阻塞行为引起的 buffer = [] while True: ready_to_read, _, _ = select.select([tcp_client_socket], [], []) if tcp_client_socket in ready_to_read: try: part = tcp_client_socket.recv(1024, flags=0x40) # 添加标志位实现非阻塞效果 if part: buffer.append(part) else: break # 如果没有更多的数据则退出循环 except OSError as err: if err.errno != errno.EWOULDBLOCK and err.errno != errno.EAGAIN: raise # 对其他类型的OSError重新引发以便调试 full_message = ''.join(buffer).decode('utf-8') print(full_message) tcp_client_socket.close() if __name__ == "__main__": main() ``` 这里引入了 Python 自带模块 `select`, 它允许我们检测文件描述符是否准备好进行 I/O 操作而无需实际执行这些操作。这有助于提高效率并且简化复杂流程管理[^3]. --- ### 总结 无论是采用简单的循环结构还是复杂的非阻塞技术都可以有效应对单一 `recv()` 呼叫局限性的情况。具体选择取决于应用场景需求和个人偏好等因素决定最佳实践路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值