Другие языки программирования и технологии

PHP и UDP-сервер: Проблема с приёмом информации

Есть udp-демон, написаный на PHP, который собирает информацию с игрового сервера. Логи до него доходят, но не полностью, если поток сильно плотный, то может пропустить 1 строку. Вот собственно код: $address="192.168.1.2"; $port=27500; while(true){ $socket=socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); socket_set_option($socket, SOL_SOCKET, SO_BROADCAST, 1); socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1); socket_bind($socket,$address,$port); $buf=socket_read($socket,100,PHP_BINARY_READ); file_put_contents("logs/cstrike.log","$buf\n",FILE_APPEND); } Вместо socket_read() использовались и socket_recv() и socket_recvfrom(), но никакой разницы нет. Каким образом можно заставить скрипт принимать все входящие сообщения?
Выше совершенно верно написали, что UDP - протокол без гарантии доставки. Если вам нужна гарантированная доставка по UDP - то это можно реализовать только внеся изменения и в сервер, и в клиент (и это, фактически, будет надстройка над UDP)

Далее:
1. Использование недоязыка PHP для создания демонов, работающих под нагрузкой - это очень плохая идея. Это же относится в большей или меньшей степени и к другим интерпретируемым языкам. Демоны для обработки данных с высокой нагрузкой надо писать на С/С++. Также неплохо бы встроить в них какую-либо обработку ошибок и нештатных ситуаций.

2. Идея построчной записи в лог в ответ на каждый пук сервера, реализованная в строчке file_put_contents("logs/cstrike.log","$buf\n",FILE_APPEND); мало подходит для применения под нагрузкой. Надо стараться минимизировать количество операций ввода-вывода

3. Идея вешать на UDP сокет, принимающий юникаст с одного заранее известного адреса SO_BROADCAST и SO_KEEPALIVE лично мне представляется очень странной :D Если уж так хочется поиграться с опциями - посмотрите в сторону SO_RCVBUF
ПО
Павел Олейник
9 623
Лучший ответ
Бауыржан Жауенов Спасибо за инфу. Но я уже решил проблему -
$buf=socket_read($socket,100,PHP_BINARY_READ);
file_put_contents("logs/cstrike.log","$buf\n",FILE_APPEND);

нужно было взять в отдельный whlie(true)
Никаким.
UDP - протокол БЕЗ гарантии доставки дейтаграмм.
Бауыржан Жауенов Самое интересное, что на perl подобное извращение работает без проблем))
главная ошибка, в том, что вы используете препроцессор гипертекста в таком неподходящем для него деле.
оставьте скрипт на перле в покое, пусть себе работает.

но если неймется - увеличьте размер буфера чтения. 100 байт видимо маловато

$address="192.168.1.2";
$port=27500;

$socket=socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_set_option($socket, SOL_SOCKET, SO_BROADCAST, 1);
socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1);
socket_bind($socket,$address,$port);

while(true) {
$len = socket_recvfrom($socket, $buf, 10000, 0, $peeraddr, $peerport);
print "DEBUG: recieved $len bytes from $peeraddr:$peerport\n";
file_put_contents("cstrike.log","$buf\n",FILE_APPEND);
}
Бауыржан Жауенов Скрипт я уже поправил, работает на ура))