<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>kocmuk.ru блог &#187; C</title>
	<atom:link href="http://kocmuk.ru/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://kocmuk.ru</link>
	<description>My own personal playground</description>
	<lastBuildDate>Wed, 01 Sep 2010 17:26:38 +0000</lastBuildDate>
	<language>ru</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>fgets () из socket-а с timeout-ом</title>
		<link>http://kocmuk.ru/2009/10/03/fgets-from-socket-with-timeout/</link>
		<comments>http://kocmuk.ru/2009/10/03/fgets-from-socket-with-timeout/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 09:22:48 +0000</pubDate>
		<dc:creator>kocmuk.ru</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://kocmuk.ru/?p=329</guid>
		<description><![CDATA[Понадобилось реализовать построчное чтение из сокета с timeout-ом. Написал для fgets () обёртку&#160;&#8212; ifgets (). Для обеспечения timeout-a используется select (). В процессе написания столкнулся с проблемой: select()  почему-то всегда выдавал timeout, хотя данные были прочтены еще не все. Strace показал странное поведение: мною читалась первая строка, далее был выход из функции чтения, но далее [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-thumbnail wp-image-332" style="margin-left: 10px; margin-right: 10px;" title="fgets из socket-а с timeout-ом" src="http://kocmuk.ru/files/2009/10/timeout-150x144.jpg" alt="timeout" width="150" height="144" align="left" />Понадобилось реализовать построчное чтение из сокета с <em>timeout</em>-ом. Написал для <em>fgets ()</em> обёртку&nbsp;&mdash; <em>ifgets ()</em>. Для обеспечения <em>timeout</em>-a используется <em>select ()</em>. В процессе написания столкнулся с проблемой: <em>select</em>()  почему-то всегда выдавал <em>timeout</em>, хотя данные были прочтены еще не все. <em></em></p>
<p><em>Strace</em> показал странное поведение: <strong>мною</strong> читалась первая строка, далее был выход из функции чтения, но далее <strong>кто-то</strong>(не я) читал всё остальное содержимое открытого сокета. Естественно, при <strong>моей</strong> попытке прочитать следующую строку из сокета, по мнению <em>select ()</em> он был пуст и происходил <em>timeout</em>.</p>
<p>Причиной это проблемы стало буферизированное чтение из сокета. Сокет опустошался в буфер, а <em>select</em>-у ничего не оставалось. После выключения буферизированного чтение, всё заработало как надо.</p>
<p>Пользоваться <strong><em>почти</em></strong> так же как <em>fgets ()</em>:</p>
<pre>int fd;
FILE *fds;

/* Делаем TCP сокет */
fd = socket(PF_INET, SOCK_STREAM, 0);

/* Параметры для соединения опущены */

/* Соединяемся */
connect(fd, (struct sockaddr *) &amp;srv_i, sizeof(srv_i));

/* Переоткрываем сокет как поток */
fds =  fdopen(fd, "w+");

/* !!! ВНИМАНИЕ! Надо обязательно выключить буферизированное чтение.
Иначе всё сразу будет прочтено в буфер и
select будет возвращать только timeout
*/
setvbuf(fds, (char *) NULL, _IONBF, 0);

/* Ну а дальше вызываем ifges() и передаём timeout в сек.
и integer descriptor для select-а
*/
if (ifgets(buf, buflen, fds, timeout, fd))
      return strlen(buf);         
if (errno == ETIMEDOUT) {
     print("Socket timeout after %d seconds", timeout);
     return (-1);
}</pre>
<p>Сама ifgets () реализована так:</p>
<pre>char *
ifgets(char *s, int size, FILE *stream, int timeout, int fd)
{
  int res;

  if (timeout) {
      do {
          res = select_fd (fd, timeout, 0);
      } while (res == -1 &amp;&amp; errno == EINTR);
      if (res &lt; = 0) {
        if (res == 0) {
                errno = ETIMEDOUT;
                return NULL;
        }
      return NULL;
      }
  }
  if(fgets(s, size, stream)) {
        return s;
  }
  return NULL;
}
/* ----------------------------------------------------------------- */
static int
select_fd (int fd, int maxtime, int writep)
{
  fd_set fds, exceptfds;
  struct timeval timeout;
  FD_ZERO (&amp;fds);
  FD_SET (fd, &amp;fds);
  FD_ZERO (&amp;exceptfds);
  FD_SET (fd, &amp;exceptfds);
  timeout.tv_sec = maxtime;
  timeout.tv_usec = 0;
  /* HPUX reportedly warns here.  What is the correct incantation?  */
  return select (fd + 1, writep ? NULL : &amp;fds, writep ? &amp;fds : NULL,
                 &amp;exceptfds, &amp;timeout);
}</pre>
<br/>
Метки: <a href="http://kocmuk.ru/tag/c/" rel="tag">C</a>
<br/>
<hr />
© Авторство и права принадлежат: <a href="http://kocmuk.ru">kocmuk.ru</a>

]]></content:encoded>
			<wfw:commentRss>http://kocmuk.ru/2009/10/03/fgets-from-socket-with-timeout/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
