简体   繁体   中英

c++: read() Hangs when reading response from server

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; 
} 

该请求必须以2个回车符和换行符终止,这在第二个示例中是丢失的。

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

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

char charI[] = "GET /index.html HTTP/1.1\r\nHost: vilive.us\r\nConnection: close\r\n\r\n";

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM