LINUX.ORG.RU

Как сервер отдаёт картинки?

 


1

1

Здравствуйте.

Я пишу маленький серверок на СИ, работа которого заключается в отдаче html-странички и css-файла. С текстовыми файлами вроде просто, открыл файл ⇨ прочитал ⇨ отдал клиенту.

Скажите, а как отдавать картинки? Если можно пример. Спасибо.


Ответ на: комментарий от i-rinat

А, про картинку без расширения все просто. Какой майм отправишь, так его клиент и попробует обработать. Но вот будет ли клиент перебирать свои хендлеры если октетстрим ему пришлешь — это скользкий момент.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Будет пытаться угадать. Эвристики у всех разные, IE как-то пытался Javascript из png файлов исполнять. Накосячили с угадывалкой.

Чтобы не угадывали, есть поле X-Content-Type-Options: nosniff.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Большое спасибо за рекомендации.

Если хочется разобраться именно с тем, как сервер делать, лучше взять другой язык.

Да, хочется научится писать на СИ и хочется разобратся в том, как пишутся сервера и написать. Другой язык (полегче) нехочу и небуду по двум причинам, во-первых мне очень-очень нравится СИ (после всяких делфи, пхп, .JS и иже с ним и прочих «раставлялок кнопок мышкой на форме»), а во-вторых, это должно работать и на «большом компьютере» и роутере с 500кб «дискового пространства» и 32М памяти.

strstr(buffer, «GET /index.html »)

Это я переделаю. Просто первые шаги.

Во-первых, sizeof — это размер в char'ах. То есть по его определению sizeof(char) всегда равен 1.

Это я знаю, но решил, что буду писать так, ущерба ведь не наносится.

Во-вторых, у тебя явно fpfile — это буфер фиксированного размера. Наверное, даже, 64 байта. Если когда-то потом будешь менять

Когда писал это, то отдавал себе отчёт. Кол-во байт подсчитано с небольшим запасом (там около 50-ти нужно, но я выделял 64, чтоб кратно было). Когда буду менять, то всё переделаю. Про переполнение я уже много знаю ))) и слежу за этим.

В-третьих, в fpfile у тебя 64 байта, а в snprintf ты передаёшь (int)strlen(patch_to_dir) + (int)strlen(name_file) + 1, которое запросто может быть больше 64-х

Как уже писал выше, там нужно около 50.

Даже если ты пишешь однопоточный сервер, нужно ввести понятие контекста, в котором сохраняются нужные для обработки запроса данные. Это понадобится, когда ты захочешь сделать сервер многопоточным, способным обрабатывать более одного подключения за раз.

Конкретно этот сервер будет работает с пятью фиксироваными файлами.

А что имеется ввиду под «нужно ввести понятие контекста, в котором сохраняются нужные для обработки запроса данные»? Скажите пожалуйста простым языком.

Спасибо.

stD
() автор топика
Ответ на: комментарий от stD

простым языком

Куда уж проще-то. Даже один браузер может сразу несколько запросов сделать. Что будет, если новое подключение придёт, пока ты разбираешься с текущим?

Такое разруливают либо через запуск отдельных потоков на каждое соединение, либо через poll() и работу на событиях. В любом случае будут ситуации, в которых несколько соединений обрабатываются одновременно. Нужно как-то их отличать. Вот то, что ты придумаешь для этого, и будет контекстом.

i-rinat ★★★★★
()
Ответ на: комментарий от stD

что с картинкой из css файла то делать?

Веб-серверу всё равно. Этот случай обрабатывается точно так же, как и прямой запрос.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Куда уж проще-то

Вот Вы только-что написали просто и понятно)))

...

Предыдущий мой сервер (TCP/UDP), сделан на форках, там ничего не падает.

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

Я сегодня получил очень много полезных советов и вразумлений, в том числе и от Вас, и это круто и благодарности моей нет предела. Но всё же, как быть с картинками из css файлов?

stD
() автор топика
Ответ на: комментарий от i-rinat

Я в комментарии выше писал:

А если запрашивать рисунок через файл style.css

body { /*background: #312f2f;*/ background: url(tux.png); margin: 30px 60px; ...

Тогда рисунка нет. Скрин консоли.

https://www.dropbox.com/s/0o1bgwfnstqttuc/2.png?dl=0

Видимо, потому что в заголовке ответа написано «text/css».

Тоесть он просто отдаёт css-файл (по размеру видно) хотя в запросе написано tux.png.

stD
() автор топика
Ответ на: комментарий от stD

Тоесть он просто отдаёт css-файл (по размеру видно) хотя в запросе написано tux.png.

Твой код — тебе виднее.

Собственно, это то, о чём я писал. Что-то работает не так, а что — уже не ясно. Пришла пора приводить код в порядок.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Буду разбираться, спасибо.

stD
() автор топика
Ответ на: комментарий от stD

А если запрашивать рисунок через файл style.css
Тогда рисунка нет. Скрин консоли.

Попробую поработать C'шной программой. Итак, я - криво написанный http сервер. Мне приходит запрос:

https://www.dropbox.com/s/0o1bgwfnstqttuc/2.png?dl=0.

Я вычитываю запрос в buffer. После чего начинаю исполнять довольно увесистую if else конструкцию:

  • ...
  • else if((strstr(buffer, "GET / ")) != NULL) - не подходит
  • else if((strstr(buffer, "GET /index.html ")) != NULL) - не подходит
  • else if((strstr(buffer, "style.css")) != NULL) - о, подходит. В запросе есть заголовок 'Referer: "http://localhost:86/style.css" '
  • else if((strstr(buffer, "png")) != NULL) - да какая разница, уже решили отдавать style.css
  • ...

Всё, устал. Пойду 503-е раздавать.

anonymous
()
Ответ на: комментарий от anonymous

Спасибо ещё раз. Все картинки отдаёт, для отдачи любого файла использую sendfile.

void read_in_file(char *name_file) 
{ 
   off_t offset = 0;
   memset(&stat_buf, 0, sizeof(stat_buf));    
   memset(fpfile, 0, 64);
   snprintf(fpfile, (int)strlen(patch_to_dir) + (int)strlen(name_file) + 1, "%s%s", patch_to_dir, name_file);
   int file = open(fpfile, O_RDONLY);
   if(file < 0) error_log("open file.");
   if(fstat(file, &stat_buf) != 0) error_log("fstat.");
   if(sendfile(client_fd, file, &offset, stat_buf.st_size) == -1) warning_access_log("sendfile."); 
   if(close(file) == -1) error_log("close.");
   if(close(client_fd) == -1) error_log("close client_fd.");
   warning_access_log(buffer);
   printf("Trans %s.\n\n", name_file);
}

При удержании F5 сервер стал падать на операции sendfile, вставил в код вот это:

signal(SIGPIPE, SIG_IGN);

Падения прекратились, но я не знаю чем может быть черевата такая функция?

...

начинаю исполнять довольно увесистую if else конструкцию:

Чем бы Вы заменили увесистую конструкцию?

Заранее спасибо.

stD
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.