【发布时间】:2016-04-02 10:08:48
【问题描述】:
我运行一个用 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;
}
【问题讨论】:
-
如果页面大于缓冲区会怎样?
-
如果第一个 recv() 返回的字节数少于仍在缓冲区中的 GET 发送字符串会怎样?
-
您需要进行更多调试,或展示您的 html 解析和缓冲区管理如何工作,或两者兼而有之。
-
另外,链接中的示例代码很糟糕。从头开始,它有令人讨厌的货物崇拜'bzero(buffer,256);'在其中,可能还有更多问题。您应该知道网络上有许多蹩脚、糟糕、糟糕和/或完全错误的服务器客户端示例:(
-
尽管每个人都说如果有可用数据,recv 会立即返回,但我可以在 Linux 上完全重现此问题。即使对方的发送返回,recv 也会阻塞。
标签: linux sockets networking tcp