#c #http #web #webserver
#c #http #веб #веб-сервер
Вопрос:
У меня возникли некоторые проблемы с пониманием того, почему я получаю ошибку сегментации на моем домашнем веб-сервере. Я пытаюсь правильно обозначить тип содержимого для документов .html и .txt. Я могу открыть HTML-файл в своем веб-браузере просто отлично, когда мой сервер запущен. Однако мой сервер закрывается из-за ошибки сегментации, когда я пытаюсь открыть документ .txt. В приведенном ниже коде я получаю проблему.
void* thread_runner(void* sockfd)
{
char buffer[256];
int n;
int sock = *(int*)sockfd;
bzero(buffer,256);
char filename[256];
bzero(filename,256);
n = read(sock,filename,255);
if (n < 0) error("ERROR reading from socket");
FILE *fp;
char file[4096];
char* word = strtok(filename, " ");
word = strtok(NULL, " ");
word ;
printf("filename = "%s"n", word);
fp = fopen(word, "r");
if (fp == NULL) {
printf("file pointer is NULLn");
return 0;
}
char string[4096];
char* extension;
bzero(string, 4096);
bzero(file, 4096);
char* word2;
word2 = strtok(word, ".");
while ((word2 = strtok(NULL, ".")) != NULL)
{
extension = word2;
}
printf("File Extension: %sn", extension);
if (strncmp(extension, "html", 4096) == 0) {
printf("HTML FILE FOUNDn");
strcat(string, "HTTP/1.1 200 OKnContent-Type: text/htmlnContent-Length: 4096 nConnection: keep-alivenn");
}
else if (strncmp(extension, "txt", 4096) == 0) {
printf("TXT FILE FOUNDn");
strcat(string, "HTTP/1.1 200 OKnContent-Type: text/plainnContent-Length: 4096nConnection: keep-alivenn");
}
ошибка возникает в этом цикле.
Я использовал нулевое значение для ‘string’.
while (fgets(file, 4096, fp))
{
strcat(string, file);
}
//printf("Sending text:%s", string);
printf("The requested file was: %s.%sn",word,extension);
n = write(sock,string,4096);
printf("file contents are %sn", string);
fclose(fp);
if (n < 0) error("ERROR writing to socket");
if (n == 0)
{
close(sock);
}
Комментарии:
1. Вы отладили построчно, чтобы увидеть, что происходит? Ваш файл находится в формате 4k? Почему вы всегда отправляете 4k, даже если объем данных меньше?
2. Для чего это
word
? Это пропускает первый символ имени файла.3. 1) Вы использовали «strcat()» несколько раз. Что произойдет, если вы переполните 4096? Где вы проверяете, чтобы этого не произошло? 2) «Магические числа», подобные
char string[4096];
иbzero(string, 4096);
, являются «плохими». Рассмотрите возможность использования#define MAXLEN 4096
,const int MAXLEN = 4096;
sizeof (string)
или эквивалента вместо этого. вместо этого.
Ответ №1:
Вы пишете после конца string
. string
в нем всего 4096 символов, но ваш цикл пытается прочитать в него весь файл, когда он продолжает вызывать strcat()
в цикле.
Вместо объединения всего файла в переменную и последующей записи всего этого, используйте fread()
для чтения файла по частям и немедленной записи их в сокет. Нет необходимости читать построчно.
size_t in;
while ((in = fread(file, 1, sizeof file, fp) > 0) {
int n = write(sock, file, in);
if (n < in) {
error("ERROR writing to socket");
}
}
close(sock);
fclose(fp);
Комментарии:
1. Теперь я получаю пустую страницу при попытке загрузить .html
2. Для полной проверки ошибок
ferror()
следует вызвать сразу послеwhile
цикла.3. @tyler7410 Вы пробовали запускать сервер под управлением отладчика, чтобы посмотреть, что он делает? Я думаю, что этот код довольно прост и должен работать.