最近有一个小项目需要一个后台服务器,其实在线数并不大,另一直对服务器编程技术中的epoll/iocp/异步之类的有所了解,但始终没有试过,了解到跨平台的库libev,libevent等在windows下面已经iocp,同时又有php.net又有一个对应的扩展pecl-libevent-0.0.4,于是说干就干,找了一篇参考文档http://vladimirbarbarosh.blogspo ... l-libevent-004.html,一番尝试后很是失望,没搞定毕竟没有搞过C++的开发,还好经过不断地尝试总算搞定. |
附件下载:Visual Studio 2005下编译php-5.3.8+pecl-libevent-0.0.4+libevent-2.0.15-stable
附编译后的php安装包 :php-5.3.8_with_libevent-2.0.15-stable.7z
再附一个php_libevent.dll适用于php-5.3.x-ts版本需要的朋友可以直接下载并在php.ini中配置即可直接使用
笔记正文内容
l 环境: Window 7 (xp应该没有问题)+ Microsoft Visual Studio 2005
l 下载资源:
n php-5.3.8http://cn.php.net/get/php-5.3.8.tar.gz/from/a/mirror
n pecl-libevent-0.0.4http://pecl.php.net/package/libevent
n libevent-2.0.15-stablehttps://github.com/downloads/libevent/libevent/libevent-2.0.15-stable.tar.gz
n PHP SDK Binary Tools http://windows.php.net/downloads/php-sdk/
下载php-sdk-binary-tools-20110915.zip
即http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip
n PHP 5.3 Depencencies http://windows.php.net/downloads/php-sdk/deps-5.4-vc9-x86.7z
l 整理编译目录
n 创建sdkphp目录至 c 盘
目录结构
n 创建编译php-5.3.8目录
cmd>cdc:\phpsdk
c:\phpsdk>bin\phpsdk_setvars.bat (注:设置环境变量)
c:\phpsdk>bin\phpsdk_buildtree.batphp-5.3.8 (注:生成php-5.3.8编译空目录)
n 准备编译所需要的源码
a) 复制php-5.3.8的源码至C:\phpsdk\php-5.3.8\vc8\x86\src
b) 复制deps-5.3-vc9-x86 源码 至 C:\phpsdk\php-5.3.8\vc8\x86\deps
c) 复制libevent-0.0.4 源码 至 C:\phpsdk\php_libevent
d) 复制libevent-2.0.15-stable 源码 至C:\phpsdk\php_libevent\libevent-2.0.15-stable
n 55
l 编译源码
n 准备工作
按下图进入vs2005的命令行模式
执行下面两个命令
Cmd>cd \
C:\phpsdk>bin\phpsdk_setvars.bat
n 编译php-5.3.8(部分指令会需要些时间)
请确保你已经执行了上面的[准备工作]
执行下面指令
C:\phpsdk>cd php-5.3.8\vc8\x86\src
C:\phpsdk\php-5.3.8\vc8\x86\src>buildconf
C:\phpsdk\php-5.3.8\vc8\x86\src>configure --disable-all --enable-cli
C:\phpsdk\php-5.3.8\vc8\x86\src>nmake
C:\phpsdk\php-5.3.8\vc8\x86\src>nmake snap
n 编译libevent-2.0.15-stable
请确保你已经执行了上面的[准备工作]
按顺序执行下面指令
C:\phpsdk>
C:\phpsdk\>cdphp_libevent\libevent-2.0.15-stable
C:\phpsdk\php_libevent\libevent-2.0.15-stable>nmake-f Makefile.nmake
n 编译pecl-libevent-0.0.4 并生成php_libevent.dll文件
请确保你已经执行了上面的[准备工作]
a) 按顺序执行下面的指令
C:\phpsdk\php_libevent>setlibeventdir= C:\phpsdk\php-5.3.8\vc8\x86\src\Release_TS\php-5.3.8-devel-VC8-x86
C:\phpsdk\php_libevent>setlibeventdir=C:\phpsdk\php_libevent\libevent-2.0.15-stable
如下图
b) 执行编译指令
cl libevent.c ^
/c ^
/Fophp_libevent.obj^
/DZEND_WIN32 ^
/DPHP_WIN32 ^
/DWIN32 ^
/DZTS=1 ^
/DZEND_DEBUG=0 ^
/DCOMPILE_DL_LIBEVENT^
/I%phpdevdir%\include\Zend^
/I%phpdevdir%\include\main^
/I%phpdevdir%\include\TSRM^
/I%phpdevdir%\include^
/I%libeventdir%\WIN32-Code^
/I%libeventdir%\include^
/I%libeventdir%
c) 执行创建php_libevent.dll指令
会报下面的错误
linkphp_libevent.obj /DLL php5ts.lib /LIBPATH:%phpdevdir%\lib libevent.lib/LIBPATH:%libeventdir% ws2_32.lib
Microsoft (R)Incremental Linker Version 9.00.30729.01
Copyright (C)Microsoft Corporation. All rights reserved.
Creating libraryphp_libevent.lib and object php_libevent.exp
libevent.lib(evutil_rand.obj): error LNK2019: unresolved external symbol __imp__CryptGenRandom@12 referencedin function _arc4_seed_win32
libevent.lib(evutil_rand.obj): error LNK2019: unresolved external symbol __imp__CryptAcquireContextA@20referenced in function _arc4_seed_win32
php_libevent.dll: fatal error LNK1120: 2 unresolved externals
解决方案:
1) 删除编译后的目标文件(obj文件)
进至目录C:\phpsdk\php_libevent\libevent-2.0.15-stable按修改时间排序查看最近生成的obj文件,删除当前目录下面的所有后缀名为obj的文件即可
2) 修改源代码
请修改./libevent-2.0.15-stable/arc4random.c中的arc4_seed_win32为下面的内容(即禁掉调用CryptAcquireContext和CryptGenRandom两个方法,即下图中灰掉背景的行)
#ifdef WIN32
#defineTRY_SEED_WIN32
static int
arc4_seed_win32(void)
{
/* This is adapted from Tor'scrypto_seed_rng() */
static int provider_set = 0;
static HCRYPTPROV provider;
unsigned char buf[ADD_ENTROPY];
/*
if (!provider_set) {
if(!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
if (GetLastError() !=(DWORD)NTE_BAD_KEYSET)
return -1;
}
provider_set = 1;
}
if (!CryptGenRandom(provider,sizeof(buf), buf))
return -1;
*/
arc4_addrandom(buf, sizeof(buf));
memset(buf, 0, sizeof(buf));
arc4_seeded_ok = 1;
return 0;
}
#endif
3) 重新编译libevent-2.0.15-stable
C:\phpsdk\php_libevent\libevent-2.0.15-stable>nmake -f Makefile.nmake
4) 重新编译pecl-libevent-0.0.4
编译之前切进目录C:\phpsdk\php_libevent 然后删除php_libevent.exp php_libevent.lib, php_libevent.obj三个文件
执行重新编译的指令
4.1) 执行编译php_libevent.c
C:\phpsdk\php_libevent>cl libevent.c ^
/c ^
/Fophp_libevent.obj ^
/DZEND_WIN32 ^
/DPHP_WIN32 ^
/DWIN32 ^
/DZTS=1 ^
/DZEND_DEBUG=0 ^
/DCOMPILE_DL_LIBEVENT ^
/I%phpdevdir%\include\Zend ^
/I%phpdevdir%\include\main ^
/I%phpdevdir%\include\TSRM ^
/I%phpdevdir%\include ^
/I%libeventdir%\WIN32-Code ^
/I%libeventdir%\include ^
/I%libeventdir%
4.2) 执行生成php_libevent.dll指令
C:\phpsdk\php_libevent>link php_libevent.obj ^
/DLL ^
php5ts.lib /LIBPATH:%phpdevdir%\lib ^
libevent.lib /LIBPATH:%libeventdir% ^
ws2_32.lib
l 测试php_libevent模块在windows下面正常工作
n 打包编译好的发布版本
移动C:\phpsdk\php-5.3.8\vc8\x86\src\Release_TS\php-5.3.8目录至c:\php-5.3.8
复制C:\phpsdk\php_libevent\php_libevent.dll 至 c:\php-5.3.8\ext目录下面
n 为php添加php_libevent模块
a) 复制c:\php-5.3.8\php.ini-production 为 c:\php-5.3.8\php.ini
b) 在php.ini中查找;extension_dir = "ext",并解除该内容前面的逗号,php.exe将会在c:\php-5.3.8\ext目录下面查找各个打开的扩展动态库文件
c) 打开php.ini在该文件的末尾添加一行内容为 extension=php_libevent.dll
d) 执行下面指令
c:\php-5.3.8>php –v (查看当前版本)
c:\php-5.3.8>php –m (查看编译好的php都装有哪些扩展)
n 通过代码测试php_libevent已经可以正常工作了
a) 从php手册下面复制一段代码放至c:\php-5.3.8\edemo.php
[code]
<?php
$socket = stream_socket_server ('tcp://0.0.0.0:2000', $errno, $errstr);
stream_set_blocking($socket, 0);
$base = event_base_new();
$event = event_new();
event_set($event, $socket, EV_READ |EV_PERSIST, 'ev_accept', $base);
event_base_set($event, $base);
event_add($event);
event_base_loop($base);
$GLOBALS['connections'] = array();
$GLOBALS['buffers'] = array();
function ev_accept($socket, $flag, $base) {
static $id = 0;
$connection = stream_socket_accept($socket);
stream_set_blocking($connection, 0);
$id += 1;
$buffer = event_buffer_new($connection, 'ev_read', NULL, 'ev_error',$id);
event_buffer_base_set($buffer, $base);
event_buffer_timeout_set($buffer, 30, 30);
event_buffer_watermark_set($buffer, EV_READ, 0, 0xffffff);
event_buffer_priority_set($buffer, 10);
event_buffer_enable($buffer, EV_READ| EV_PERSIST);
// we need to save both buffer and connection outside
$GLOBALS['connections'][$id] = $connection;
$GLOBALS['buffers'][$id] = $buffer;
}
function ev_error($buffer, $error, $id) {
event_buffer_disable($GLOBALS['buffers'][$id], EV_READ | EV_WRITE);
event_buffer_free($GLOBALS['buffers'][$id]);
fclose($GLOBALS['connections'][$id]);
unset($GLOBALS['buffers'][$id], $GLOBALS['connections'][$id]);
}
function ev_read($buffer, $id) {
while ($read = event_buffer_read($buffer, 256)) {
var_dump($read);
}
}
?>
[/code]
b) 执行上面的文件
c:\php-5.3.9>php.exeedemo.php
c) 用测试软件SocketTool进行测试
SocketTool.exe下载地址: http://ishare.iask.sina.com.cn/f/7826641.html?from=like
n
l Centos 5.x下面安装php_libevent扩展
n 安装默认的libevent及开发版本
#yum –y installlibevent libevent-devel
n 安装php_libevent扩展
#pecl installchannel://pecl.php.net/libevent-0.0.4
n 配置php.ini使php支持libevent
#echo “extension=libevent.so”> /etc/php.d/libevent.ini
查看扩展是否有效
#php –m|greplibevent
l 附参考资料:
Compile php-5.3.6+ pecl-libevent-0.0.4 + libevent-2.0.11-stable
http://vladimirbarbarosh.blogspot.com/2011/05/compile-php-536-pecl-libevent-004.html