php socket 模型及效率问题
// 创建套接字
socket_create();
// 绑定
socket_bind();
// 监听
socket_listen();
// 主体, 死循环
while(true){
// select模型, 取出可读套接字列表
socket_select();
foreach(sockets) {
// 如果是监听连接请求端口的套接字
if(is listensocket) {
// 接受请求
socket_accept();
}
else {
// 读取封包
socket_recv();
// 处理用户动作 {问题就在这}
process();
}
}
}
关于php做服务端的效率, 我想这里是个问题吧。
在每处理一个用户的动作的时候, 整个循环被阻塞在这里, 导致其他的连接不能接受, 其他用户的动作请求不能被处理。 直到process()函数返回才能处理下一个动作。
处理一个用户动作的时候, 可能还要涉及到数据库访问等, 可能比较耗时。
不知道有没有哪位大仙有解决办法呢。
我想的是, 如果能做一个动作队列, 这里的循环只负责接收数据, 然后把数据包保存在一个队列里, 就去接收下一个用户的封包。
另一个线程(不知道PHP怎么实现线程, 或是能不能实现)从队列中抽取每一个用户的动作请求来处理它。。
或着process()函数能不能做成非阻塞的, 让它可以立即返回。。
小弟初学,如有可笑之处,请见谅!
飞翼浮游炮
12 years, 2 months ago
Answers
这个问题我也遇到过到,比如打开两个终端,telnet socket服务端,如果其中一个不返回,另一个终端总是等待。最后使用fork子进程方式解决,大概代码如下,你可以参考下:
死循环部分
do {
$msgsock = socket_accept($socket);
$pid = pcntl_fork();
if($pid == -1) {
// fork error ;
}else if($pid) {
socket_close($msgsock);
}else {
$buf = socket_read($msgsock,1024,PHP_NORMAL_READ);
$ret = func($buf); //调用函数处理接收到的内容
socket_write($msgsock,$ret,strlen($ret));
socket_close($msgsock);
//posix_kill(posix_getpid(),0);
exit();
}
}while(true)
抖M的墨鱼
answered 12 years, 2 months ago