gpt4 book ai didi

PHP socket_write 失败仅在下次调用时返回错误

转载 作者:行者123 更新时间:2023-12-03 11:52:43 24 4
gpt4 key购买 nike

我正在尝试通过 PHP 套接字发送数据,客户端是一个 Arduino 设备,当我多次发送时它接收数据正常,但是如果我重置客户端(Arduino 设备),它会在几秒钟内重新启动,它说连接到PHP套接字,然后当我想再次发送数据时socket_send()它默默地失败了,PHP socket_send()没有在第一个实际错误时返回错误,只有在我第二次尝试(并失败)时才返回错误(“发送零字节”)。收到此错误时,我创建另一个 socket_accept()并成功发送消息。
什么可能导致这种情况?我希望它能够正确检测丢失的连接,以便在需要时重新发送数据。
感觉就像它将数据发送到旧连接并且仅在第二次尝试时才意识到它,这可能吗?
这可以通过 socket_select() 修复吗? ?我很难理解它的作用。
说明:如果客户端重新启动并再次连接,则向其发送数据返回 int ,然后 false , false , false (除非我取消设置 $accept 并再次执行 socket_accept())。如果客户端保持离线,那么发送总是返回 int , int , int .int是发送的字符串的大小。

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Could not create socket\n");

// reuse any existing open port to avoid error
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);

$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");

$result = socket_listen($socket) or die("Could not set up socket listener\n");


do{

if(!isset($accept)){
echo "\nwaiting for clients";
$accept = @socket_accept($socket) or die("Could not accept incoming connection");
echo "\nclient connected";
}

// memcached will return a message here like: "my message\r\n"
$message_to_send = $memcached->get('my_socket_message');

if($message_to_send!=''){

echo "\nsending: ".$message_to_send;

$total_data_sent = @socket_send($accept, $message_to_send, strlen($message_to_send), MSG_EOR);

// if data was not send (sent to an old connection ?!)...
// then clear $accept, so a new connection is accepted
// and keep the my_socket_message variable, so message is sent again

if($total_data_sent === false){
echo "\nSEND FAILED, will retry message: ".$message_to_send;
unset($accept);
} else {
$memcached->delete('my_socket_message');
}

}

} while (true);

最佳答案

我已经进行了一些实验,并且能够重现该问题。这是我的解决方案(可能不是最好的方法,但有效):

@socket_send($accept, $message_to_send, strlen($message_to_send), MSG_EOR);
$dataSent = @socket_write($accept, '', 0);

if ($dataSent === false) {
unset($accept);
// ...
编辑
我想出了一个更简洁的解决方案。我们只是做什么 socket_send功能是应该做的。返回 falseint接收的字节数。
在接收端,您只需解码消息( $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 正是这样做的 - 确保已收到数据。也许我们在这里还缺少一些东西。

关于PHP socket_write 失败仅在下次调用时返回错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63199965/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com