我正在尝试通过PHP套接字发送数据,客户端是Arduino设备,当我多次发送数据时,它可以正常接收数据,但是如果我重置客户端(Arduino设备),它会在几秒钟后重新启动,它说它已连接到PHP套接字,然后当我想通过socket_send()
重新发送数据时,它默默地失败了,PHP socket_send()
并没有在第一个实际错误上返回错误,只是第二次尝试(并且失败),只有这样它才会返回错误(“已发送零字节”)。收到此错误后,我将创建另一个socket_accept()
并成功发送消息。
这可能导致什么?我希望它能够正确检测到丢失的连接,以便在需要时可以重新发送数据。
感觉像是将数据发送到旧的连接,并且仅在第二次尝试时才意识到,这可能吗?
可以用socket_select()
解决此问题吗?我很难理解它的作用。
说明:如果客户端重新启动并再次连接,则向其发送数据将返回int
,然后返回false
,false
,false
(除非我取消设置{{1 }},然后再次执行$accept
。如果客户端保持脱机状态,则发送总是返回socket_accept()
,int
,int
。
int
是发送的字符串的大小。
int
答案 0 :(得分:1)
我做了一些尝试,并能够重现该问题。这是我的解决方法(也许不是最好的方法,但是可行):
Task
我想出了一个更简洁的解决方案。我们只是执行@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
尽管这行得通,但我认为TCP确实可以做到-确保已接收到数据。也许我们在这里还缺少什么。
答案 1 :(得分:1)
这是我最终使用的,它似乎工作得很好。
它等待来自客户端的答复/确认,如果没有收到确认,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);
}