2 回答
TA贡献1865条经验 获得超7个赞
我进行了一些实验并能够重现该问题。这是我的解决方案(也许不是最好的方法,但有效):
@socket_send($accept, $message_to_send, strlen($message_to_send), MSG_EOR);
$dataSent = @socket_write($accept, '', 0);
if ($dataSent === false) {
unset($accept);
// ...
编辑
我想出了一个更简洁的解决方案。我们只是做函数socket_send应该做的事情。返回false或int接收到的字节数。
在接收端,您只需解码消息 ( $data) 并发strlen回$data['payload']。客户端也可以验证它是否已收到这样的所有数据。为此,只需与strlen进行比较即可。如果你真的很偏执,你也可以实现一些校验和。$data['payload']$data['length']
服务器使用的代码send而不是socket_send:
function send($client, $message) {
$messageLength = strlen($message);
$data = [
'length' => $messageLength,
'payload' => $message
];
$jsonData = json_encode($data);
try {
@socket_send($client, $jsonData, strlen($jsonData), MSG_EOR);
$response = @socket_read($client, 1024);
if (intval($response) !== $messageLength) {
return false;
}
} catch (Exception $e) {
return false;
}
return $response;
}
尽管这可行,但我认为 TCP 正是这样做的——确保数据已被接收。也许我们仍然缺少一些东西。
TA贡献2003条经验 获得超2个赞
这就是我最终使用的,看起来效果很好。它等待来自客户端的回复/确认,如果没有收到确认,则message_to_send保留,连接被清除,在下一个循环中它重新连接并重试发送现有的message_to_send.
$total_data_sent = @socket_send($accept, $message_to_send, strlen($message_to_send), MSG_EOR);
// set a timeout for waiting a reply, in this case 500 milliseconds
socket_set_option($accept, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>0, "usec"=>500000));
// read a reply, which should be "ok" (text sent by client)
$reply = socket_read($accept, 1024);
// if reply was not "ok", then unset the connection and will reconnect on next loop
if($reply != "ok"){
unset($accept);
}
// if reply was "ok", then clear this message as it was successfuly sent
if($reply == "ok"){
unset($message_to_send);
}
- 2 回答
- 0 关注
- 108 浏览
添加回答
举报