PHP与Python Socket通信问题:recv()未等待客户端响应
PHP客户端刷新页面时Python Socket服务端收到空字符串的原因及解决办法
问题场景
搭建PHP页面(客户端)与Python脚本(服务端)的Socket通信:PHP页面设有按钮,点击后向服务端发送"next"指令,该功能正常运行。但刷新PHP页面时,未发送任何数据,服务端的recv()却接收到空字符串并执行后续代码。
客户端代码(client.php)
<?php $host = '127.0.0.1'; $port = 5353; $socket = socket_create(AF_INET, SOCK_STREAM, 0) or die('Could not create socket\n'); $result = socket_connect($socket, $host, $port) or die('Could not connect to server\n'); if(isset($_POST['btnNext'])) { $msg_to_server = 'next'; socket_write($socket, $msg_to_server, strlen($msg_to_server)) or die('Could not send data to server\n'); $msg_from_server = socket_read($socket, 1024) or die('Could not read server response\n'); echo 'Server said : ' . $msg_from_server; } ?> <form action='' method='POST' > <button name='btnNext' type='submit'>Next</button> </form>
服务端代码(server.py)
import socket host = '127.0.0.1' port = 5353 server_socket = socket.socket(socket.AF_INET, SOCK_STREAM) server_socket.bind((host, port)) server_socket.listen(5) while True: client_socket, addr = server_socket.accept() # doesn't wait for the client response : msg_from_client = client_socket.recv(5000).decode() print('Client said : ' + msg_from_client)
原因分析
- PHP脚本执行逻辑:每次刷新PHP页面(包括首次加载),整个脚本都会从头执行。不管是否点击按钮,都会执行
socket_create和socket_connect,与服务端建立TCP连接。 - 连接关闭触发空数据:无POST请求时,PHP未调用
socket_write发送数据,但脚本执行完毕后会自动关闭Socket连接。此时客户端向服务端发送FIN包,服务端recv()在连接正常关闭且无数据传输的情况下,会返回空字符串。 - 服务端无判断逻辑:服务端每次接新连接后立刻调用
recv(),未判断接收内容是否为空,导致空字符串被后续代码处理。
解决办法
方案一:仅触发按钮时建立Socket连接
修改PHP代码,将Socket创建、连接和通信逻辑放到按钮触发的判断分支内,避免无意义连接:
<?php $host = '127.0.0.1'; $port = 5353; if(isset($_POST['btnNext'])) { $socket = socket_create(AF_INET, SOCK_STREAM, 0) or die('Could not create socket\n'); $result = socket_connect($socket, $host, $port) or die('Could not connect to server\n'); $msg_to_server = 'next'; socket_write($socket, $msg_to_server, strlen($msg_to_server)) or die('Could not send data to server\n'); $msg_from_server = socket_read($socket, 1024) or die('Could not read server response\n'); echo 'Server said : ' . $msg_from_server; socket_close($socket); // 主动关闭连接,避免资源泄漏 } ?> <form action='' method='POST' > <button name='btnNext' type='submit'>Next</button> </form>
方案二:服务端增加空数据判断
修改Python服务端代码,接收到空字符串时直接关闭连接并跳过后续处理:
import socket host = '127.0.0.1' port = 5353 server_socket = socket.socket(socket.AF_INET, SOCK_STREAM) server_socket.bind((host, port)) server_socket.listen(5) while True: client_socket, addr = server_socket.accept() msg_from_client = client_socket.recv(5000).decode() # 空数据则关闭连接,跳过后续逻辑 if not msg_from_client: client_socket.close() continue print('Client said : ' + msg_from_client) # 可选:添加客户端回复逻辑 # client_socket.sendall(b"Command received") client_socket.close()
内容的提问来源于stack exchange,提问作者Raphaël Goisque
相关产品推荐
相关产品推荐

