2

我正在开发一个用objective-c/cocoa 编写的fastcgi 开发工具包,它模仿AppKit/UIKit 的行为和结构(应用程序委托、运行循环、事件队列等)。我已经完成了关于 fastcgi、libfcgi、使用 libfcgi 的 fastcgi 目标 c 实现的功课,但我很遗憾地意识到,为了使其 100%“可可”,我必须自己实现协议,从从头开始(libfcgi 被设计为“循环”的方式与 CoreFoundation RunLoops 和事件队列不兼容)。

话虽如此,根据 fastcgi.com 上的文档(FCGI 白皮书),fastcgi-responder 应用程序有以下几种情况:

  1. 该应用程序是 Web 服务器的本地应用程序,并由后者根据需要生成,以满足传入的请求
  2. 该应用程序对于 Web 服务器来说是本地或远程的,但 Web 服务器假定它已经在运行并通过域套接字或 tcp/ip 套接字与其通信。

我对第二种情况很好,因为我可以控制我希望我的应用程序监听的套接字路径/IP 地址和端口:我知道我的通信通道在哪里。

我遇到的问题是第一种情况。我一直在筛选fci_stdio.cfcgiapp.c查看FCGX_Accept_r,等FCGX_InitRequestFCGX_Stream我似乎无法找到它试图读取的套接字。

不,这不是stdin因为它被劫持并“封装”到fastcgi.com 文档中指定的FCGI_FILE结构中。fcgi_stdio.h我承认我的 posix 编程时代已经远远落后于我,而且我有点生疏了。我肯定错过了一些东西。

我试过stdin在我的应用程序中收听,它出现了 posix 错误 57(未指定的错误)并且没有数据。这是我在示例应用程序的日志中获得的输出示例:

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. ** 它可以超时,因为我没有在代码中做任何事情来响应请求或将任何数据发送回服务器(我离那个很远)。

如果服务器根据请求动态创建套接字,应用程序如何知道要监听(读取/写入)的套接字路径?

4

1 回答 1

2

最后,经过更多的挖掘、反复试验、大量的咖啡和一些新鲜空气,我来到了http://www.fastcgi.com/devkit/doc/fcgi-spec.html上的 FastCGI 规范中的一段

2.2 文件描述符

当应用程序开始执行时,Web 服务器会留下一个单独的文件描述符 FCGI_LISTENSOCK_FILENO。该描述符指的是由 Web 服务器创建的侦听套接字。

FCGI_LISTENSOCK_FILENO 等于 STDIN_FILENO。标准描述符 STDOUT_FILENO 和 STDERR_FILENO 在应用程序开始执行时关闭。应用程序确定它是使用 CGI 还是 FastCGI 调用的可靠方法是调用 getpeername(FCGI_LISTENSOCK_FILENO),该方法返回 -1,并且对于 FastCGI 应用程序将 errno 设置为 ENOTCONN。

Web 服务器对可靠传输、Unix 流管道 (AF_UNIX) 或 TCP/IP (AF_INET) 的选择隐含在 FCGI_LISTENSOCK_FILENO 套接字的内部状态中。

因此,我真的不应该关心套接字的实际物理路径,因为它是通过流传递给我的应用程序的STDIN。我需要做的就是倾听。我们不是吗?!

因为我知道要听什么,所以我可以使用(请参阅此处[NSFileHandle acceptConnectionInBackgroundAndNotify]的Apple 文档)来听套接字并响应请求。

哇!

于 2013-05-02T20:23:22.600 回答