Я написал простой http-сервер, который, кажется, работает, но у меня возникают проблемы при попытке доступа через браузер - PullRequest
1 голос
/ 29 мая 2011

Основная проблема, которая у меня возникает, заключается не в самом коде, однако я разместил код на всякий случай. Во-первых, когда я запускаю сервер и использую «telnet localhost 46745» в отдельном терминале, я получаю успешное соединение с localhost. Затем я набираю «GET /hello.html HTTP / 1.1». Файл hello.html находится в каталоге, из которого запускается сервер. В любом случае, метод GET возвращает обе строки кода в файле hello.html. Хорошо, это похоже на работу. Проблема заключается в том, что я захожу в firefox и в браузере набираю «http://localhost:46745/hello.html",», и я не получаю никаких сообщений об ошибках, но браузер просто вращается и говорит «Ожидание localhost ...». возможные проблемы (код или в браузере), которые могут быть причиной этой проблемы. Я гуглил в течение нескольких часов безрезультатно, и, да, это домашнее задание. Спасибо.

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>   /* Internet domain header */
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <signal.h>

#define SA struct sockaddr
#define SERVER_PORT  46745
#define MAX_LINE     256
#define BUFFER_SIZE 10000
#define MAX_PENDING  5

int  soc ;    /* socket for server */

void signal_catcher( int the_sig ) {
  printf("terminating the server socket number %d\n",soc) ;
  close( soc ) ;
  exit(0) ;
}

int main() {
  struct sockaddr_in serv_addr, clnt_addr;
  char buf[BUFFER_SIZE];
  int len, new_s, bytes_read;
  char response[MAX_LINE];
  char fileExt[MAX_LINE];
  char* token;

  /* remove socket for server when terminating */
  if( signal(SIGINT, signal_catcher ) == SIG_ERR ){
    perror("SIGINT") ;
    exit(13) ;
  }

  if( signal(SIGQUIT, signal_catcher ) == SIG_ERR ){
    perror("SIGQUIT") ;
    exit(14) ;
  }

  /* set up listening socket soc, passive open */
  if ( (soc = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
    perror("server: socket"); 
    exit(1);
  }

  /* build address data structure */
  serv_addr.sin_family = AF_INET ;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY) ;
  serv_addr.sin_port = htons(SERVER_PORT) ;

  if (bind(soc, (SA *)  &serv_addr, sizeof(serv_addr)) < 0) {
    perror("server: bind");
    close(soc);
    exit(1);
  }

  if(listen(soc, MAX_PENDING) < 0) {
    perror("server: listen");
    close(soc);
    exit(1);
  }

  printf("Socket number for server = %d\n",soc);

  /* accept connection, then receive and print text */
  while ( 1 ) {
    len = sizeof(clnt_addr) ;
    if ( (new_s = accept(soc, (SA *)  &clnt_addr , &len) ) < 0 ) {
      perror("server:  accept"); 
      close(soc);
      exit(1);
     }

  printf("\nConnect from host %s, port %hd\n",inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port) );

  memset(buf,0x0,BUFFER_SIZE);    //  init line 

  while( len = recv( new_s, buf, sizeof( buf ), 0 ) ) {
    if (strstr(buf,"GET")) {
      token=strtok(buf," ");
      token=strtok(NULL," ");
      sprintf(fileExt,".%s",token);
    FILE *fp;
    fp=fopen(fileExt, "r");
    if (fp!=NULL) {
              send(new_s, "HTTP/1.1 200 OK\r\n\r\n", 23, 0);
              while(bytes_read=fread(response, 1, sizeof(response), fp)) {
                int length = strlen(response)-1;
                if(response[length] == '\n') {
                  response[length] = 0;
                }
                send(new_s, response, bytes_read, 0 );
                fclose(fp);
              }
        } else {
                send(new_s, "HTTP/1.1 404 Not Found\r\n\r\n", 30, 0);
              }
     }// end if strstr
 else {
  send(new_s, "HTTP/1.1 400 Invalid Request\r\n\r\n", 36, 0);
 }
  }// end while from recv

  }// end while(1)
  close ( new_s );
return(0);
}

Ответы [ 3 ]

4 голосов
/ 29 мая 2011

В вашем ответе клиенту есть несколько ошибок.Сначала вы выводите \n\n перед строкой HTTP/1.1 XXX Some Status.HTTP/1.1 должно быть первым.Там нет \n\n до этого.Во-вторых, вы выводите \n s после него.Спецификация HTTP указывает, что вы должны использовать \r\n, а не \n (хотя Firefox должен уметь это обрабатывать).Наконец, для ваших кодов состояния 400 и 404 вы не возвращаете никакого контента.Вы, вероятно, должны, даже если он пуст.

3 голосов
/ 29 мая 2011

Технически терминатор строки - CRLF ("\ r \ n"), а не LF ("\ n").

Возможно, это не ваша проблема, но это, безусловно, проблема.

0 голосов
/ 29 мая 2011

Вы не говорите, выводит ли ваш сервер свои сообщения вроде:

Connect from host ...

, так что это одна вещь, которую нужно искать.Возможно, что сообщения никогда не доходят до вашего сервера.

Но, независимо от этого, вы должны получить себе копию WireShark (бесплатно) или другую программу сетевого анализатора, чтобы вы могли точно знать, что именнопроисходит под прикрытием.

Это очень поможет при отладке подобных проблем.

...