The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
отправка данных, сокеты, !*! SnugForce, 26-Июн-05, 14:58  [смотреть все]
Как работает функция send для отправки данных? Какого время ее выполения? Какой интервал брать между последовательными вызовами? Заранее спасибо..
  • отправка данных, сокеты, !*! Alexander S. Salieff, 18:45 , 27-Июн-05 (1)
    >Как работает функция send для отправки данных? Какого время ее выполения? Какой
    >интервал брать между последовательными вызовами? Заранее спасибо..

    При "наобумном" вызове send'а на блокированном (а он такой по умолчанию) сокете выполнение программы блокируется на неопределенное время, пока не удастся отправить часть данных (совсем не обязательно будут отправлены все предложенные данные, возможно их придется отправлять частями).
    Для гарантированной отправки данных с форматированием по временной сетке можно использовать 2 метода: неблокированный сокет с обработкой EAGAIN, либо демультиплексирование дескриптора на запись (poll/select). Я предпочитаю последнее, обертка для send'а с таймаутом выглядит у меня вот так:

    int t_send(int s, const void *msg, size_t len, int flags, int timeout)
    {
    int my_timeout = timeout;
    return t_send(s, msg, len, flags, &my_timeout);
    }

    int t_send(int s, const void *msg, size_t len, int flags, int * timeout)
    {
    if (*timeout<=0) return TNETWORK_ERR;
    int curr_len=len;
    int curr_timeout=*timeout;
    while (curr_len>0 && curr_timeout>0)
      {
      timeb t1;
      ftime(&t1);
    //Крутим poll в течении timeout
      struct pollfd ufds={s, POLLOUT, 0};
      int poll_ret = poll(&ufds, 1, curr_timeout);
      if (poll_ret<0)
       {
       if (errno==EINTR) //Прерывание сигналом
        {
        timeb t2;
        ftime(&t2);
        curr_timeout-=((t2.time-t1.time)*1000+t2.millitm-t1.millitm);
        continue;
        }
       else return TNETWORK_ERR;
       }
      if (poll_ret==0)
       return TNETWORK_TIMEOUT;
      if (!(ufds.revents&POLLOUT))
       return TNETWORK_ERR;
      int l=send(s, (unsigned char *)msg+(len-curr_len), curr_len, flags);
      if (l<0)
       {
       if (errno==EINTR)
        {
        timeb t2;
        ftime(&t2);
        curr_timeout-=((t2.time-t1.time)*1000+t2.millitm-t1.millitm);
        continue;
        }
       else return TNETWORK_ERR;
       }
      curr_len-=l;
      timeb t2;
      ftime(&t2);
      curr_timeout-=((t2.time-t1.time)*1000+t2.millitm-t1.millitm);
      }
    *timeout-=curr_timeout;
    return (len-curr_len);
    }

    Соответственно 1ый вариант просто с таймаутом, 2ой - с таймаутом и возвратом реально потраченного на операцию времени (часто бывает нужно для корекции именно той самой временной сетки)




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру