理解recv阻塞永远的原因

时间:2016-04-02 10:08:48

标签: linux sockets networking tcp

我运行一个用C编写的Linux程序,该程序通过解析HTTP响应定期接收数据,处理一些数字,然后通过另一个网页的HTTP GET报告结果。

我的问题是,有时,其中一个实例会冻结"。

查看top我可以看到它处于sk_wait_data状态,并且附加调试程序会显示它被recv调用阻止。

以下是执行TCP连接的代码的最小版本(它是从http://www.linuxhowtos.org/C_C++/socket.htm改编而来的):

int connectTCP(const char* host, const char* page, int portno) {
    int sockfd;

    struct sockaddr_in serv_addr;
    struct hostent *server;

    // Create socket //
    sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockfd < 0) 
        error("ERROR opening socket");


    // Get ip from hostname //
    server = gethostbyname(host);
    if (server == NULL)
        error("ERROR, can not find host\n");

    memset((char *) &serv_addr, 0, sizeof(serv_addr));


    serv_addr.sin_family = AF_INET;
    memcpy((char *)&serv_addr.sin_addr.s_addr,   // Destination
            (char *)server->h_addr,  // Source
            server->h_length);       // Size
    serv_addr.sin_port = htons(portno);

    // Conect to socket //
    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
        error("ERROR connecting");

    return sockfd;

}

char* httpGet(const char* host, const char* page, int portno) {
  int sockfd, n;

  sockfd = connectTCP(host, page, portno);
  memset(buffer, 0, sizeof(buffer));

  sprintf(buffer, "GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n", page, host);

  n = send(sockfd,buffer,strlen(buffer), 0);

  if (n < 0) 
    error("ERROR writing to socket");

  int count = 0;
  do {
    n = recv(sockfd, buffer + count, BUFFER_MAX_SIZE - count, 0);
    if (n < 0) {
      error("ERROR reading from socket");

    }

    count += n;
  } while(n != 0);

  close(sockfd);

  return buffer;
}

1 个答案:

答案 0 :(得分:0)

代码中的错误:

  1. 如果recv()返回零,您将关闭套接字并停止阅读。

  2. 如果recv()返回-1,则应报告错误,关闭套接字并停止读取,除非您设置了读取超时且errno为EAGAIN / EWOULDBLOCK,在这种情况下你应该处理超时但是适合你的申请。