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

时间:2011-03-19 21:07:10

标签: c++ sockets user-input

我有两个版本的代码。在一个版本中,如果用户输入短语“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; 
} 

2 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:1)

请切换到现代版本的HTTP。我觉得很惊讶你的服务器同意回复,因为请求不是远程有效的HTTP。

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

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

请注意Host标头,它允许您与执行虚拟主机的网站进行通信,例如指向相同IP地址的... stackoverflow.com和superuser.com。他们只依靠Host标头来确定用户是否想要访问stackoverflow.com或superuser.com。

此外,您应该在使用套接字后关闭套接字描述符。