Có rất nhiều thông tin trên trang web này về cách xử lý lỗi được trả về không đồng bộ từ Dịch vụ Thông báo Đẩy của Apple trong PHP. Tôi đã đưa ra một phương pháp trong PHP mà dường như làm việc khá tốt, nhưng tôi muốn một số phản hồi.Phương pháp xử lý mã thông báo thiết bị cho Dịch vụ Thông báo Đẩy của Apple với PHP
- Việc sử dụng fflush() có đúng không? Tôi đã nhìn thấy nó trong một số ví dụ nhưng không phải tất cả.
- Tôi không thể báo lỗi cho mã thông báo thiết bị cố ý xấu. Tại sao?
- Giải pháp này có thể mở rộng thành hàng nghìn thiết bị (giả sử bộ nhớ tối đa của PHP được tăng đủ) không?
- Các sự cố khác?
Ghi chú:
- Mã thông báo thiết bị được lưu trữ trong một mảng khi bắt đầu.
- Nó không phải là không đồng bộ nhưng nó sẽ kiểm tra lỗi (quá khứ) sau khi gửi mỗi thông báo và kiểm tra thêm một lần nữa sau khi thông báo cuối cùng.
- Nó sử dụng định dạng thông báo "hiện đại" mới hơn so với định dạng ban đầu hoặc mở rộng.
- Nó sẽ gửi chỉ mục của mảng mã thông báo làm số nhận dạng cho APNS.
- Nó sử dụng hàm checkAppleErrorResponse() đọc 6 byte đầu tiên và trả về false hoặc số nhận dạng (chỉ mục) không thành công để có thể sao lưu và tiếp tục với mã thông báo tiếp theo. (Tất cả mã thông báo được gửi sau khi thất bại sẽ bị vô hiệu.)
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'passphrase', $iosCertPassphrase);
stream_context_set_option($ctx, "ssl", "local_cert", $iosCertKey);
$fp = NULL;
$errno = NULL;
$errstr = NULL;
// same payload for all
$item2 = chr(2) . pack("n", strlen($payload)) . $payload; // payload item has id 2, a 2-byte length ("n") containing length of payload, then payload
$errorID = -1;
while ($errorID !== false) {
$fp = stream_socket_client($iosHost . ':' . $iosPort, $errno, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if ($fp === FALSE) {
echo('Failed to create socket');
break;
}
stream_set_blocking($fp, 0);
for ($id = $errorID + 1 ; $id < sizeof($iosTokens); $id++) {
$errorID = false;
$item1 = chr(1) . pack('n', 32) . pack("H*", $iosTokens[$id]['device_token']); // device token item has 1-byte id 1, 2-byte length ("n") containing 32, then 32-byte device token
$item3 = chr(3) . pack('n', 4) . pack('N', $id); // notification identifier has 1-byte id 3, 2-byte length ("n") containing 4, then 4-byte identifier
$frame = $item1 . $item2 . $item3;
$msg = chr(2) . pack("N", strlen($frame)) . $frame; // for "modern" push notification format, msg has 1-byte id 2, 4-byte length ("N") containing the length of the frame, then frame
fwrite($fp, $msg);
$errorID = checkAppleErrorResponse($fp);
fflush($fp);
if ($errorID !== false) // if there's an error, stop now
break;
}
// if done with for loop and no errors, pause for a sec and check one last time
if ($errorID === false) {
$read = array($fp);
$null = null;
$changedStreams = stream_select($read, $null, $null, 0, 1000000);
//check if it is actually false
if ($changedStreams === false)
{
//close stream when done.
socket_close($fp);
fclose($fp);
}
elseif ($changedStreams > 0)
{
// set the error and redo starting after errorID index
$errorID = checkAppleErrorResponse($fp);
}
}
}
}
Lưu ý, không liên quan đến câu hỏi thực tế của bạn: bạn có thể làm điểm nhấn bằng cách đặt một không gian ở phía trước mỗi dấu gạch ngang của bạn. Nó có thể làm cho nó trông đẹp hơn một chút. –
Khi tôi thử điều đó, nó sẽ không nhận ra hàng chục dòng mã đầu tiên dưới dạng mã, vì vậy tôi để lại dấu gạch ngang ... – ScottyB
... Huh. Thật ki quặc. Có lẽ vì Markdown nghĩ rằng bạn muốn thêm mã như một phần của các điểm bullet. Nó không thực sự là một việc lớn, dù sao đi nữa. Chỉ nghĩ rằng tôi muốn chỉ ra nó. –