apache / php模块套接字问题

时间:2012-01-25 13:29:05

标签: php c sockets apache2 preforking

我在Debian Lenny 32bit下运行Apache2.2服务器+ PHP 5.2。 我在C中构建了一个“简单”的php模块扩展。 这个扩展做了一件事:通过套接字调用一个小的“回显服务器”并等待结果(在两端发送/接收'A')。

进入 prefork-mpm模型,我将socket设置为全局var PHP结构。 因此,全局扩展源听起来像这样:

在mymodule.h中

    ZEND_BEGIN_MODULE_GLOBALS(hello)
        int socket;
    ZEND_END_MODULE_GLOBALS(hello)

    #ifdef ZTS
    #define HELLO_G(v) TSRMG(hello_globals_id, zend_hello_globals *, v)
    #else
    #define HELLO_G(v) (hello_globals.v)
    #endif

在mymodule.c中

...
static int sock_create(char *address, int port, SA_IN *servaddr)
{
   int s;

   s = socket(AF_INET, SOCK_STREAM, 0);

   if (!s)
     return 0;

   memset(servaddr, 0, sizeof(SA_IN));
   servaddr->sin_family = AF_INET;
   servaddr->sin_port = htons((unsigned short)port);
   servaddr->sin_addr.s_addr = inet_addr(address);

   return s;
}




int send_recv(int sock, char ch)
 {
   int r;
   char tmp[2];

   tmp[0]=ch;
   tmp[1]=0;

   r = send(sock, 'A', 1, 0);

   if (r<=-1)
     return -1;

   r = recv(sock, tmp, 1, 0);

   if (r<=-1)
     return -2;

   return (int) tmp[0];

 }



 PHP_FUNCTION(cmd_echo)
 {
   int item, r=0;
   SA_IN addr;

   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &item)==FAILURE)
     WRONG_PARAM_COUNT;


   if (HELLO_G(sa)==0)
   {
     HELLO_G(sa) = sock_create("server_ip", 4500, &addr);

     r = connect(HELLO_G(sa), (SA *) &addr, sizeof(SA));

     send_recv(HELLO_G(sa), 'a');
     RETURN_LONG(6);
   }
   else
   {
     send_recv(HELLO_G(sa), 'b');     // <---- trouble here, hangs...
     RETURN_LONG(7);
   }

   RETURN_LONG(1);
  }

听起来很完美...... 每次Apache分叉新进程时,我都会创建一个新连接(sa == 0) 如果Apache,一段时间后,决定“重用”现有的进程,我的socket是 - 已经连接 - (而且我很确定)会在没有创建套接字的情况下将数据发送到服务器。只是表现得像某种“套接字池”

但是麻烦来了......

由于未知原因,在Apache尝试重用开放套接字的情况下,send_recv()会挂起send()命令。当然,套接字处于阻塞模式,但为什么会出现这种情况?

(顺便说一句,如果我运行相同的代码(当然没有PHP代码)到一个带有几个send_recv的可执行文件中,一切都运行得很好!)

Apache似乎锁定套接字!??

有什么想法吗?

0 个答案:

没有答案