linux - 了解 recv 永远阻塞的原因

标签 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. 如果 recv() 返回零,您应该关闭套接字并停止读取。

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

关于linux - 了解 recv 永远阻塞的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36371888/

相关文章:

c - 发送以太网数据包时额外填充?

Java Socket - 如何在三点之间发送和接收信息?

java - 多客户端广播中的 MulticastSocket 与 DatagramSocket

c - 操作系统如何为文件执行缓冲

c - Linux登录和strcmp

windows - 在 Linux 上忽略 Apache 指令 'ScriptInterpreterSource'

c - 如何比较c中的两个ip地址?

linux - 如何将 Web 开发从 Windows 转移到 Linux

python - 如何在常规文件上生成 POLLPRI 事件?

php - SocketIO 和 Apache