2013-05-01 12 views
1

Я работаю над комплектом fastcgi dev, написанным в объективе c/cocoa, который имитирует поведение и структуру AppKit/UIKit (приложения удаляются, runloops, очереди событий и т.д). Я сделал домашнее задание по fastcgi, libfcgi, реализациям fastcgi-цели c с использованием libfcgi, и я пришел к грустной осознанию того, что для того, чтобы сделать это на 100% «Какао», мне пришлось бы реализовать протокол сам, начиная с scratch (способ, которым libfcgi предназначен для «loop», не очень хорошо справляется с CoreFoundation RunLoops и очередями событий).Каков путь сокета для пользовательского приложения FCGI, созданного локальным HTTP-сервером? (например, apache/mod_fcgid, lighttpd/mod_fastcgi и т. д.)

Это, как говорится, есть следующие случаи для применения FastCGI-ответчика в соответствии с документацией (FCGI Whitepaper) в fastcgi.com:

  1. Приложение является локальным для веб-сервера и порождены последний по мере необходимости для выполнения входящих запросов
  2. Приложение является локальным или удаленным для веб-сервера, но веб-сервер предполагает, что он уже запущен и связывается с ним через сокет домена или сокет tcp/ip.

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

Проблема, с которой я столкнулся, - это первый сценарий. Я просеиваю throuh fci_stdio.c и fcgiapp.c глядя на FCGX_Accept_r, FCGX_InitRequest, FCGX_Stream и тому подобное, и я не могу найти, с каким сокетом он пытается читать.

Нет, это не stdin как это получает угнали и «окутан» в FCGI_FILE структуры в fcgi_stdio.h, как указано в документации на fastcgi.com. Я признаю, что мои дни программирования программирования намного отстают от меня, и я немного ржавый. Я определенно чего-то не хватает.

Я пробовал слушать stdin в моем приложении, и он приходит с ошибкой posix 57 (Unspecified error) и никаких данных. Вот пример вывода я получаю в журнале на примере приложения:

2013-05-01 11:40:01.486 Test-FCGIKit[2477:707] /Users/catalin/Sites/fcgi/Test-FCGIKit-CocoaBundle.bundle/Contents/MacOS/Test-FCGIKit 
2013-05-01 11:40:01.495 Test-FCGIKit[2477:707] applicationWillFinishLaunching: 
2013-05-01 11:40:01.497 Test-FCGIKit[2477:707] startRunLoop 
2013-05-01 11:40:01.498 Test-FCGIKit[2477:707] applicationDidFinishLaunching: 
2013-05-01 11:40:01.500 Test-FCGIKit[2477:707] * Waiting for events 
2013-05-01 11:40:01.501 Test-FCGIKit[2477:707] didReadToEndOfStdIn: 
2013-05-01 11:40:01.502 Test-FCGIKit[2477:707] NSConcreteNotification 0x7fb3d9806670 {name = NSFileHandleReadToEndOfFileCompletionNotification; object = <NSConcreteFileHandle: 0x7fb3d8c15030>; userInfo = { 
    NSFileHandleError = 57; 
    NSFileHandleNotificationDataItem = <>; 
}} 
2013-05-01 11:40:01.504 Test-FCGIKit[2477:707] * Waiting for events 
2013-05-01 11:40:01.508 Test-FCGIKit[2477:707] * Processed event 
2013-05-01 11:40:01.510 Test-FCGIKit[2477:707] * Waiting for events 
[Wed May 01 11:40:41 2013] [warn] [client 127.0.0.1] mod_fcgid: read data timeout in 40 seconds 
[Wed May 01 11:40:41 2013] [error] [client 127.0.0.1] Premature end of script headers: Test-FCGIKit 
2013-05-01 11:40:43.337 Test-FCGIKit[2477:707] Caught SIGTERM. Terminating. 
2013-05-01 11:40:43.338 Test-FCGIKit[2477:707] terminate: 
2013-05-01 11:40:43.339 Test-FCGIKit[2477:707] applicationShouldTerminate: 
2013-05-01 11:40:43.343 Test-FCGIKit[2477:707] quit 
2013-05-01 11:40:43.345 Test-FCGIKit[2477:707] applicationWillTerminate: 
  • Пожалуйста, не вводить в заблуждение именами сообщений: они предназначены, чтобы быть точно так же, как и AppKit/UIKit но они не от NSApplication. ** Это нормально для него до таймаута, поскольку я ничего не делаю в коде для ответа на запрос или отправки каких-либо данных обратно на сервер (я довольно далек от этого).

Как приложение может узнать, какой путь к сокету прослушивать (читать/записывать), если сервер создает динамический динамический запрос по запросу?

ответ

1

Наконец, после того, как немного больше рытья, проб и ошибок, много кофе и немного свежего воздуха я пришел acress абзац в спецификации FastCGI на http://www.fastcgi.com/devkit/doc/fcgi-spec.html

2.2 Файловые дескрипторы

Веб-сервер оставляет один файловый дескриптор, FCGI_LISTENSOCK_FILENO, открытый, когда приложение начинает выполнение. Этот дескриптор относится к прослушивающему сокету, созданному веб-сервером.

FCGI_LISTENSOCK_FILENO равно STDIN_FILENO. Стандартные дескрипторы STDOUT_FILENO и STDERR_FILENO закрываются, когда приложение начинает выполнение. Надежный метод для приложения для определения того, был ли он вызван с использованием CGI или FastCGI, - это вызов getpeername (FCGI_LISTENSOCK_FILENO), который возвращает -1 с errno, установленным в ENOTCONN для приложения FastCGI.

Выбор надежного транспорта веб-сервера, потоки Unix-потоков (AF_UNIX) или TCP/IP (AF_INET), подразумевается во внутреннем состоянии гнезда FCGI_LISTENSOCK_FILENO.

Так, значит, я должен действительно не заботиться о фактическом физическом пути сокета, так как он передается в мое приложение через STDIN поток. Мне нужно только послушать. Разве мы не все?!

Поскольку я знаю, что слушать, я могу использовать [NSFileHandle acceptConnectionInBackgroundAndNotify] (см. Документацию Apple here), чтобы прослушивать сокет и отвечать на запросы.

Whew!