За последние 24 часа нас посетили 62114 программистов и 1791 робот. Сейчас ищут 919 программистов ...

Отправка данных через сокет UDP на PHP

Тема в разделе "Прочие вопросы по PHP", создана пользователем tipati, 14 окт 2015.

  1. tipati

    tipati Новичок

    С нами с:
    14 окт 2015
    Сообщения:
    15
    Симпатии:
    0
    Есть прога на смартфон - GPS-трекер, отправляет данные по UDP на прописанный сервер и порт. Отправляет простым текстом, строка с данными, разделенными пробелами. Получать проблем нет, нашел, разобрался (раньше не имел дела с UDP вообще, так-то уже лет 15 вожусь потихоньку). Проблема - программа требует посылки ответа, иначе начинает капризничать, копить точки в кэше, высылать и повторно и т.д.

    http://doro.poltava.ua/gpsm/gpsmta.html#p17

    Читаю про UDP и не понимаю, как это. Там вроде нужно знать IP-адрес трекера и т.п...

    Получаю честно найденным в енторнетах кодом: http://pastebin.com/d46jYZPN

    Как отправить ответ?
     
  2. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    UDP очень похож на TCP. На php в работе с ними вообще разницы нет. Где-то в районе 53-й строчки используй функцию http://php.net/socket_write для передачи данных в сокет после прочтения (если данные были получены).
     
  3. tipati

    tipati Новичок

    С нами с:
    14 окт 2015
    Сообщения:
    15
    Симпатии:
    0
    Читал. Попытался применить. Что-то не понимаю, видимо.

    Последняя попытка была socket_send($socket,$message,count($message),MSG_DONTROUTE);
    Warning: socket_send(): unable to write to socket [89]: Destination address required in ...

    socket_write($socket,$message) там, где вы сказали:
    Warning: socket_write(): unable to write to socket [89]: Destination address required in ...

    Откуда его брать?
    ЗЫ: по TCP тоже ессно ничего не передавал. В смысле, с сокетами вообще не работал. Может какой-то фак для чайников по сокетам нужно читать?
     
  4. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Код (Text):
    1. socket_write($socket, 'all right!');
     
  5. tipati

    tipati Новичок

    С нами с:
    14 окт 2015
    Сообщения:
    15
    Симпатии:
    0
    Поправил уже выше. Та же ерунда.
     
  6. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Код (Text):
    1.          if (False === ($r = socket_read($socket, 1024))) {
    2.             $errorcode = socket_last_error();
    3.             $errormsg = socket_strerror($errorcode);
    4.             if ($errorcode!='11') { echo "error reading : [$errorcode] $errormsg <br>\n"; }
    5.          } else {
    6.                   socket_write($socket, 'all right!');
    7.          }
    как-то так
     
  7. tipati

    tipati Новичок

    С нами с:
    14 окт 2015
    Сообщения:
    15
    Симпатии:
    0
    Ну так и сделано. Только было "если не пуст результат", вот если угодно через else:

    Код (PHP):
    1.                 while(1){
    2.                      usleep(0.5 * 1000000); // 0.5 seconds
    3.                      if (False === ($r = socket_read($socket, 1024))) {
    4.                         $errorcode = socket_last_error();
    5.                         $errormsg = socket_strerror($errorcode);
    6.                         if ($errorcode!='11') { echo "error reading : [$errorcode$errormsg <br>\n"; }
    7.                      } else {
    8.                         $a=explode(" ",$r);
    9.                         socket_write($socket,$a[0]);
    10.                         echo $r;
    11.                      }
    12.                      if ($r!='') { echo "<pre>".date("d.m.Y H:i:s",$a[1])." - ".$r."</pre>\n"; }
    13.                      flush_buffers();
    14.                 } 
    Выхлоп:

    Код (PHP):
    1. Socket created 
    2. Socket bind OK 
    3. Warning: socket_write(): unable to write to socket [89]: Destination address required in /blablabla/gpstracking/tracking_web.php on line 69 352019030137388 1444843381 55.0000 38.0000 20 355 14 151 00 63 29 0 0
    4. 14.10.2015 20:23:01 - 352019030137388 1444843381 55.0000 38.0000 20 355 14 151 00 63 29 0 0
    5. Warning: socket_write(): unable to write to socket [89]: Destination address required in /blablabla/gpstracking/tracking_web.php on line 69 352019030137388 1444843136 55.54735 38.900351 1 79 18 146 00 64 28 0 0
    6. 14.10.2015 20:18:56 - 352019030137388 1444843136 55.0000 38.0000 1 79 18 146 00 64 28 0 0
    ЗЫ: магическое "олл райт" тоже не помогает ;-)

    PHP, JavaScript, SQL и другой код пишите внутри тегов
    Код ( (Unknown Language)):
    1. [b]php][/b]Тут код[b][/[/b][b]code][/b][/color]
     
  8. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Попробуй после 39-й добавить
    Код (Text):
    1. socket_listen($socket);
    2. socket_accept($socket);
    и убери установку сокета в неблокирующим режим.
     
  9. tipati

    tipati Новичок

    С нами с:
    14 окт 2015
    Сообщения:
    15
    Симпатии:
    0
    Попробовал.
    socket_listen(): unable to listen on socket [95]: Operation not supported
    socket_accept(): unable to accept incoming connection
    socket_write(): unable to write to socket [89]: Destination address required

    пичаль

     
  10. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Точняк.
    Эти функции для TCP, в котором существует установка соединения. В контексте соединения хранится информация о IP-адресе противоположной стороны. Функция socket_read() из той же оперы.

    socket_recvfrom() умеет сохранять в переменную ip-адрес клиента.
    вместо
    Код (Text):
    1. if (False === ($r = socket_read($socket, 1024))) {
    попробуй
    Код (Text):
    1. if (False === ($ok = socket_recvfrom($socket, $r, 1024, 0, $remote_ip, $remote_port))) {
    переменные $r, $remote_ip и $remote_port создавать не обязательно, поскольку они принимаются по ссылке и используются для сохранения информации.
    Потом соответственно вместо
    Код (Text):
    1. socket_write
    делай
    Код (Text):
    1.  
    2. $response = 'All right!';
    3. socket_sendto($socket, $response, strlen($response), 0, $remote_ip, $remote_port);
     
  11. tipati

    tipati Новичок

    С нами с:
    14 окт 2015
    Сообщения:
    15
    Симпатии:
    0
    Уже лучше. Правда, после повторного запуска скрипта
    Warning: socket_recvfrom(): unable to recvfrom [11]: Resource temporarily unavailable
    И ничего с этим поделать не могу... Странно, вроде скрипт прибивается, переменные очищаются... Порт слушается...
    $ sudo lsof -i :9999
    COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
    /usr/sbin 13670 www-data 22u IPv4 183259206 0t0 UDP *:9999
     
  12. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    ОС не удаляет сокет без специальной команды, используй socket_close().
     
  13. tipati

    tipati Новичок

    С нами с:
    14 окт 2015
    Сообщения:
    15
    Симпатии:
    0
    А в старой версии скрипта все нормально прибивалось убийством процесса.
    Как я могу использовать socket_close(), когда скрипт работает в бесконечном цикле и выйти из него можно только перезагрузив страницу, а тогда ни о каком resource $socket не может быть и речи - он давно потерян?
     
  14. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632