За последние 24 часа нас посетили 16746 программистов и 1641 робот. Сейчас ищут 857 программистов ...

Сокет TCP

Тема в разделе "PHP для новичков", создана пользователем uniken1, 6 июл 2015.

  1. uniken1

    uniken1 Новичок

    С нами с:
    12 ноя 2014
    Сообщения:
    4
    Симпатии:
    0
    Здравствуйте.

    Объясните пожалуйста принцип работы с сокетами, в частности с протоколом TCP, на таком примере:
    Код (PHP):
    1. $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
    2. socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 3, 'usec' => 0));
    3. socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 3, 'usec' => 0));
    4. socket_connect($socket,"192.168.100.100",9900);
    5. $n = microtime(true);
    6. while (socket_recv($socket, $t, 8192, 0)) {
    7.         var_dump($t);
    8. }
    9. echo "mt: ".(microtime(true)-$n)."\n";
    10.  
    У меня получается, что цикл выполняется дважды один раз получает данные(меньше чем указан размер буфера), второй раз пока не истечет таймаут(потому что время выполения скрипта больше 3сек).
    Почему socket_recv не завершается, если в сокете ничего нет?
    Или я должен точно знать до байта, размер информации которую мне отправит сервер?
    Или я должен сравнивать размер буфера кол-вом прочитанных байт, и если данных меньше чем размер буфера, то данные кончились?

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

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Так в этом и смысл таймаута в TCP.
    Данные по TCP передаются пакетами. Какой-нибудь очередной пакет может не дойти, условно говоря, 100 раз подряд. В это время твой сокет на другом конце будет стоять пустым и ждать данные, пока не истечет таймаут.
    Сокет TCP не должен закрываться лишь по тому, что закончились данные в этот момент. Он предполагает двухсторонний обмен, поэтому без специальных условий ни одна сторона не должна его закрывать. Например, если ты принимаешь данные HTTP, то ты должен распарсить заголовок Content-Length и читать заданное количество байтов, после чего закрыть сокет вручную. А если заголовка нет, то закрыть сокет после двух пустых строк. Или сначала отправить ответ, а потом закрыть сокет.
     
  3. uniken1

    uniken1 Новичок

    С нами с:
    12 ноя 2014
    Сообщения:
    4
    Симпатии:
    0
    Т.е. любым способом я всегда точно должен знать сколько байт мне надо получить из сокета, правильно?
     
  4. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Да. А в чем задача целиком? Может быть уже существуют решения.
     
  5. uniken1

    uniken1 Новичок

    С нами с:
    12 ноя 2014
    Сообщения:
    4
    Симпатии:
    0
    Локально - просто разбираюсь с сокетами. Глобально делаю vnc прокси.