c ++: read () Зависает при чтении ответа с сервера - PullRequest
2 голосов
/ 20 марта 2011

У меня есть две версии этого кода.В одной версии, если пользователь вводит фразу «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 ]

6 голосов
/ 20 марта 2011

Запрос должен быть завершен двумя парами возврата каретки и перевода строки, это отсутствует во втором примере.

char charI[] = "GET /index.html\r\n\r\n";
1 голос
/ 20 марта 2011

Пожалуйста, переключитесь на современную версию 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.

Кроме того, вы должны закрыть дескриптор сокета, когда вы закончите с использованием сокета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...