c++: read() 从服务器读取响应时挂起
我有这个代码的两个版本。在一种版本中,如果用户输入短语“GET /index.html”,服务器会正确响应。在第二个版本中,内置了“GET /index.html”短语,而不提示用户。第二个版本在读取服务器响应时挂起,知道为什么吗?
第一个版本 - 提示用户输入短语
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[10000];
portno = atoi("85");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error((char *)"ERROR opening socket");
server = gethostbyname("vilive.us");
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error((char *)"ERROR connecting");
printf("Please enter the message: ");
memset(buffer,0,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error((char *)"ERROR writing to socket");
memset(buffer,0,256);
n = read(sockfd,buffer,500);
if (n < 0)
error((char *)"ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}
第二个版本 - 自动发送“GET /index.html” - 此版本挂起
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[10000];
//TEST
char getI[16];
getI[0]='G';
getI[1]='E';
getI[2]='T';
getI[3]=' ';
getI[4]='/';
getI[5]='i';
getI[6]='n';
getI[7]='d';
getI[8]='e';
getI[9]='x';
getI[10]='.';
getI[11]='h';
getI[12]='t';
getI[13]='m';
getI[14]='l';
getI[15]='\0';
portno = atoi("85");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error((char *)"ERROR opening socket");
server = gethostbyname("vilive.us");
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error((char *)"ERROR connecting");
/*printf("Please enter the message: ");
memset(buffer,0,256);
fgets(buffer,255,stdin);*/
n = write(sockfd,getI,strlen(getI));
if (n < 0)
error((char *)"ERROR writing to socket");
memset(buffer,0,256);
n = read(sockfd,buffer,500);
if (n < 0)
error((char *)"ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}
I have two versions of this code. In one version if the user inputs the phrase "GET /index.html" the server responds properly. In the second version, the "GET /index.html" phrase is built in without prompting the user. The second version hangs when reading a response from the server, any idea why?
First Version - Prompts user for phrase
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[10000];
portno = atoi("85");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error((char *)"ERROR opening socket");
server = gethostbyname("vilive.us");
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error((char *)"ERROR connecting");
printf("Please enter the message: ");
memset(buffer,0,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error((char *)"ERROR writing to socket");
memset(buffer,0,256);
n = read(sockfd,buffer,500);
if (n < 0)
error((char *)"ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}
Second Version - Automatically sends "GET /index.html" - This one hangs
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[10000];
//TEST
char getI[16];
getI[0]='G';
getI[1]='E';
getI[2]='T';
getI[3]=' ';
getI[4]='/';
getI[5]='i';
getI[6]='n';
getI[7]='d';
getI[8]='e';
getI[9]='x';
getI[10]='.';
getI[11]='h';
getI[12]='t';
getI[13]='m';
getI[14]='l';
getI[15]='\0';
portno = atoi("85");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error((char *)"ERROR opening socket");
server = gethostbyname("vilive.us");
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error((char *)"ERROR connecting");
/*printf("Please enter the message: ");
memset(buffer,0,256);
fgets(buffer,255,stdin);*/
n = write(sockfd,getI,strlen(getI));
if (n < 0)
error((char *)"ERROR writing to socket");
memset(buffer,0,256);
n = read(sockfd,buffer,500);
if (n < 0)
error((char *)"ERROR reading from socket");
printf("%s\n",buffer);
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该请求必须以 2 个回车符和换行符对终止,这在第二个示例中缺失。
The request must be terminated with 2 carriage return and line feed pairs, this is missing in your second example.
请切换到现代版本的 HTTP。我发现您的服务器同意回复是令人惊讶的,因为该请求不是远程有效的 HTTP。
在您的情况下,这将是一个合适的 HTTP/1.1 请求,
请注意 Host 标头,它允许您与进行虚拟托管的站点进行通信,例如指向相同 IP 地址的 stackoverflow.com 和 superuser.com。他们仅依靠 Host 标头来确定用户是否想要访问 stackoverflow.com 还是 superuser.com。
另外,当您使用完套接字后,应该关闭套接字描述符。
Please, switch to a modern version of HTTP. I find it amazing that your server agrees to reply, as the request isn't remotely valid HTTP.
This would be a suitable HTTP/1.1 request in your situation
note the Host header, that allow you to talk with sites that do virtual hosting, like ... stackoverflow.com and superuser.com that points to the same ip address. they only rely on the Host header to figure out if the user want to access stackoverflow.com or superuser.com.
Also, your should close the socket descriptor when you are done using the socket.