C++ c++;:从服务器读取响应时,read()挂起

C++ c++;:从服务器读取响应时,read()挂起,c++,sockets,user-input,C++,Sockets,User Input,我有两个版本的代码。在一个版本中,如果用户输入短语“GET/index.html”,服务器将正确响应。在第二个版本中,内置了“GET/index.html”短语,而不提示用户。第二个版本在从服务器读取响应时挂起,知道为什么吗 第一个版本-提示用户输入短语 #include <stdio.h> #include <strings.h> #include <stdlib.h> #include <sys/types.h> #include &l

我有两个版本的代码。在一个版本中,如果用户输入短语“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; 
} 
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效错误(字符*消息)
{ 
佩罗尔(味精);
出口(0);
}
int main(int argc,char*argv[])
{ 
int sockfd,端口号,n;
服务地址中的结构sockaddr\u;
结构主机*服务器;
字符缓冲区[10000];
portno=atoi(“85”);
sockfd=套接字(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
错误((字符*)“打开套接字时出错”);
server=gethostbyname(“vilive.us”);
如果(服务器==NULL){
fprintf(stderr,“错误,没有这样的主机\n”);
出口(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(端口号);
if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
错误((字符*)“连接错误”);
printf(“请输入消息:”);
memset(缓冲区,0256);
fgets(缓冲区,255,标准输入);
n=写入(sockfd,buffer,strlen(buffer));
if(n<0)
错误((char*)“写入套接字时出错”);
memset(缓冲区,0256);
n=读取(sockfd,缓冲器,500);
if(n<0)
错误((char*)“从套接字读取错误”);
printf(“%s\n”,缓冲区);
返回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; 
} 
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效错误(字符*消息)
{ 
佩罗尔(味精);
出口(0);
}
int main(int argc,char*argv[])
{ 
int sockfd,端口号,n;
服务地址中的结构sockaddr\u;
结构主机*服务器;
字符缓冲区[10000];
//试验
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=套接字(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
错误((字符*)“打开套接字时出错”);
server=gethostbyname(“vilive.us”);
如果(服务器==NULL){
fprintf(stderr,“错误,没有这样的主机\n”);
出口(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(端口号);
if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
错误((字符*)“连接错误”);
/*printf(“请输入消息:”);
memset(缓冲区,0256);
fgets(缓冲区,255,标准输入法);*/
n=写入(sockfd、getI、strlen(getI));
if(n<0)
错误((char*)“写入套接字时出错”);
memset(缓冲区,0256);
n=读取(sockfd,缓冲器,500);
if(n<0)
错误((char*)“从套接字读取错误”);
printf(“%s\n”,缓冲区);
返回0;
} 

必须使用2对回车和换行符对终止请求,这在第二个示例中缺失

char charI[] = "GET /index.html\r\n\r\n";

请切换到现代版本的HTTP。我发现您的服务器同意回复是令人惊讶的,因为请求不是远程有效的HTTP

在您的情况下,这将是一个合适的HTTP/1.1请求

char charI[] = "GET /index.html HTTP/1.1\r\nHost: vilive.us\r\nConnection: close\r\n\r\n";
请注意主机标题,它允许您与虚拟主机站点进行对话,如。。。stackoverflow.com和superuser.com指向同一ip地址。它们仅依赖主机标头来确定用户是否要访问stackoverflow.com或superuser.com


另外,当您使用完套接字后,应该关闭套接字描述符。

是的,它是一台专用服务器,我的isp会阻止端口80。所以我在端口85上运行一个web服务器。此外,这是一个快速修改的代码,不知道我为什么要使用atoi()…为什么要使用如此古老的HTTP protcol版本?甚至令人惊讶的是,你的服务器同意回复,而我的服务器不同意。说真的,如果不是HTTP/1.1,至少切换到HTTP/1.0这只是一个快速测试,我对HTTP协议几乎一无所知。我计划将此代码用于微控制器项目。在第一种情况下,
\r
也可能丢失,但服务器似乎忽略了这一点。