ioctl with FIONREAD与recvfrom

2691阅读 0评论2012-06-14 areece
分类:C/C++

一块vxworks中的一片老代码,tftp client在调用tftpsend的时候,陷入死循环,代码很简单,如下:

点击(此处)折叠或打开

  1. FOREVER
  2.         {
  3.           TFTP_MSG    trash;

  4.          if (ioctl (pTftpDesc->sock, FIONREAD, (int)&amount) == ERROR)
  5.          return (ERROR);

  6.          if (amount == 0)        /* done - socket cleaned out */
  7.          break;

  8.      (void) recvfrom (pTftpDesc->sock, (caddr_t) &trash, sizeof
  9.                   (TFTP_MSG), 0, (SOCKADDR *) NULL, (int *) NULL);
  10.      }

  11.      /* break out to send loop in order to resynch by reresending */

  12.      if (ntohs (pTftpReply->th_block) == (blockReply - 1))
  13.      break;

  14.      return (ERROR);            /* things look bad - return */
  15.      }
代码中,先通过ioctl看看sock中到底有多少数据可读,如果可读,再调用recvfrom真正的读取数据。但是在我们的设备中,发现ioctl返回成功,并且amount肯定大于0,但是recvfrom的时候,却返回了ERROR,于是悲剧性地死循环了。

看看源代码,发现以FIONREAD调用ioctl时,并没有检查socket状态,只是取回接收缓存中的字节数,而recvfrom会检查状态,可能会返回失败,或者接收不到数据,当然recvfrom在处理socket状态时,处理比较复杂,这里想说的是前面两种情况并不是完全一一对应的关系:即并不一定是接收缓存中有数据,调用recvfrom就能够接收。源代码中没有处理recvfrom返回值,导致出现死循环,在vxworks的后续版本(6.x)已经修改为检查返回值,如果出错,就要退出循环。

点击(此处)折叠或打开

  1. if (recvfrom (pTftpDesc->sock, (caddr_t) &trash,
  2.                           sizeof (TFTP_MSG), 0, (struct sockaddr *) NULL,
  3.                           (int *) NULL) == ERROR)
  4.                           return (ERROR);


上一篇:[读书笔记] HMAC
下一篇:一粒沙就是一个世界