The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"Непонятное поведение программы с Интернет-сокетом"
Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (Сеть, сокеты)
Изначальное сообщение [ Отслеживать ]

"Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от AlterFritz (ok) on 21-Ноя-10, 16:11 
Ниже приведена программа простейшего Web-сервера, из которого выброшено всё, что не относится к проблеме.
А проблема состоит в том, что браузер не получает ответа на запрос. Ответ формируется операторами, обозначенными в нижеследующем коде (функция process_request) как "проблемная группа".
Telnet при этом ответ получает.
Если не читать запроса или поставть операторы проблемной группы перед чтением запроса - браузер получает ответ.
В чём дело?
Проблему я решил, прочитав запрос в предке до fork, а не в потомке, как это делается в программе ниже. Но всё равно непонятно.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
int make_server_socket()
{
        struct sockaddr_in saddr;
        int sock_id=sock_id = socket(AF_INET,SOCK_STREAM,0);
        bzero((void*)&saddr,sizeof(saddr));
        if(INADDR_ANY) // проверка для тех систем, где эта константа не ноль
        saddr.sin_addr.s_addr = htonl(INADDR_ANY); // обработка вне зав-ти от номера смаого сервера
        saddr.sin_port = htons(12345);
        saddr.sin_family = AF_INET;
        if(bind(sock_id,(struct sockaddr*)&saddr,sizeof(saddr)) != 0) return -1;
        if(listen(sock_id,1) !=0) return -1;
        return sock_id;
}
void process_request(int fd)
{
        FILE*fp=fdopen(fd,"r+");
        char request[BUFSIZ+1];
        fgets(request,BUFSIZ,fp);
/*------------ проблемная группа --------------------*/
        fprintf(fp, "HTTP/1.0  Error\r\n");
        fprintf(fp, "Content-Type: text/html\r\n");
        fprintf(fp, "Connection: close\r\n\r\n");
        fprintf(fp, "404 ERROR\r\n");
        fclose(fp);
}
int main(int argc,char *argv[])
{
        int sock,fd;
        sock =  make_server_socket();
        while(1) {
                fd = accept(sock,NULL,NULL);
                if(fork()==0) {
                        process_request(fd);
                        exit(0);
                }
                close(fd);
        }
        close(sock);
}
Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от guest email(??) on 21-Ноя-10, 17:14 
> /*------------ проблемная группа --------------------*/
>         fprintf(fp, "HTTP/1.0  Error\r\n");

Попробуйте отдавать нормальных HTTP заголовок.
fprintf(fp, "HTTP/1.0  404\r\n");

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

2. "Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от AlterFritz (ok) on 21-Ноя-10, 18:31 
>> /*------------ проблемная группа --------------------*/
>>         fprintf(fp, "HTTP/1.0  Error\r\n");
> Попробуйте отдавать нормальных HTTP заголовок.
> fprintf(fp, "HTTP/1.0  404\r\n");

Нет, проблема не в этом. Ведь если передать этот неправильный заголовок и всё остальное ДО fgets - всё будет нормально - браузер выдаст страницу. Похоже, здесь какие то тонкости работы с потоками у потомков. Использование read и write не приводит к проблемам!

Ответить | Правка | ^ к родителю #1 | Наверх | Cообщить модератору

3. "Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от guest email(??) on 21-Ноя-10, 19:05 
а у меня ваш пример (правил только инклюды под систему) и так работает.
Попробуйте так:
fflush(fp);
fclose(fp);
close(fd);
Ответить | Правка | ^ к родителю #2 | Наверх | Cообщить модератору

4. "Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от AlterFritz (ok) on 21-Ноя-10, 19:28 
> а у меня ваш пример (правил только инклюды под систему) и так
> работает.
> Попробуйте так:
> fflush(fp);
> fclose(fp);
> close(fd);

Попробовал. Увы. И, вроде, последний close не нужен, так как есть fclose. Но всё одинаково. Конечно, можно было бы грешить на браузер, но не работают оба: Firefox и Opera. И опять же telnet-то получает ответ.

Ответить | Правка | ^ к родителю #3 | Наверх | Cообщить модератору

5. "Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от AlterFritz (ok) on 21-Ноя-10, 19:39 
Тот же результат на почти другой ОС: Fedora 8 и Fedora 14.
Ответить | Правка | ^ к родителю #3 | Наверх | Cообщить модератору

6. "Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от Аноним (??) on 21-Ноя-10, 20:14 
Попробуйте использовать анализатор пакетов wireshark, чтобы посмотреть что реально передается по сети...

> Тот же результат на почти другой ОС: Fedora 8 и Fedora 14.

Ответить | Правка | ^ к родителю #5 | Наверх | Cообщить модератору

8. "Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от AlterFritz (ok) on 21-Ноя-10, 21:17 
> Попробуйте использовать анализатор пакетов wireshark, чтобы посмотреть что реально передается
> по сети...
>> Тот же результат на почти другой ОС: Fedora 8 и Fedora 14.

Попробовал, хотя я в этом не сильно понимаю. Результат такой.
При "нормальной" работе идёт 8 пакетов
1. SYN
2. SYN
3. ACK
4. GET /file HTTP/1.1
5. ACK
6. HTTP/1.0 Error
7. ACK
8. RST

При втором "нормальном" запуске получается 16 пакетов
1. SYN
2. SYN
3. ACK
4. HTTP/1.0 Error
5. ACK
6. FIN
7. GET /file HTTP/1.1
8. RST
9. SYN
10. SYN
11. ACK
12. HTTP/1.0 Error
13. ACK
14. FIN
15. GET /favicon.ico HTTP/1.1
16. RST

Третий запуск аналогичен первому

При "ненормальной" работе тоже сначала 8 пакетов
1. SYN
2. SYN
3. ACK
4. GET /file HTTP/1.1
5. ACK
6. FIN
7. FIN
8. ACK

Потом вываливается сразу 42 пакета, среди которых 5 подряд запросов GET, и также без пакета HTTP/1.0 Error.
Такая картина почти всегда: я всегда видел создание 5 подряд потомков с одним и тем же запросом. Я объяснял это тем, что браузер пытается получить ответ перепосылая запрос.

Другая картина - при работе с read-write
Первый запрос дал 16 пакетов

1. SYN
2. SYN
3. ACK
4. GET /file HTTP/1.1
5. ACK
6. HTTP/1.0 Error
7. ACK
8. Continuation or on-HTTP Traffic
9. ACK
10. Continuation or on-HTTP Traffic
11. ACK
12. Continuation or on-HTTP Traffic
13. ACK
14. FIN
15. FIN
16. ACK

Как это понимать? Буду вспоминать ТСР.

Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

10. "Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от AlterFritz (ok) on 22-Ноя-10, 00:18 
> Попробуйте использовать анализатор пакетов wireshark, чтобы посмотреть что реально передается
> по сети...
>> Тот же результат на почти другой ОС: Fedora 8 и Fedora 14.

Проблема, видимо, проста
Надо считывать запрос до конца, а у меня только один fgets торчит.
С telnet-ом запрос считывался за один раз. Wireshark все таки помог.

Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

7. "Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от meantraitor on 21-Ноя-10, 20:48 
> Нет, проблема не в этом. Ведь если передать этот неправильный заголовок и
> всё остальное ДО fgets - всё будет нормально - браузер выдаст
> страницу. Похоже, здесь какие то тонкости работы с потоками у потомков.
> Использование read и write не приводит к проблемам!

А чем отличается fread от read, помните?

Ответить | Правка | ^ к родителю #2 | Наверх | Cообщить модератору

9. "Непонятное поведение программы с Интернет-сокетом"  +/
Сообщение от AlterFritz (ok) on 21-Ноя-10, 21:22 
>> Нет, проблема не в этом. Ведь если передать этот неправильный заголовок и
>> всё остальное ДО fgets - всё будет нормально - браузер выдаст
>> страницу. Похоже, здесь какие то тонкости работы с потоками у потомков.
>> Использование read и write не приводит к проблемам!
> А чем отличается fread от read, помните?

Буферизованный ввод-вывод. Но fread я не пробовал. Прекрасно работает и с fgets, если его сделать в предке, а в потомке уже писать в стандартный вывод. Проблема возникает если fgets выполнять в потомке. А read тоже работает как то мне непонятно, судя по картине пакетов.

Ответить | Правка | ^ к родителю #7 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру