php中connect,PHP异步并发connect

以前写过一个multi_http()的函数,就是异步地做http请求,后来再次看那段代码的时候,发现不少问题:

1. 我只在发送、接受数据的时候使用了异步,connect的时候还是同步的

2. 由于我发送数据的时候使用的是http1.0,所以接受数据的时候靠feof()判断结束就很方便了;如果使用http1.1,而且connection:keep-alive; 那么就不是那么简单了

如果需要异步并发,建议使用curl,今天看了一下,curl在异步并发请求的时候,connect、send、recv都是异步的。测试代码:

muti_curl.php

// 创建一对cURL资源

$ch1 = curl_init();

$ch2 = curl_init();

// 设置URL和相应的选项

curl_setopt($ch1, CURLOPT_URL, "http://phpor.net/tools/whoami.php");

curl_setopt($ch1, CURLOPT_HEADER, 0);

curl_setopt($ch2, CURLOPT_URL, "http://phpor.net/tools/whoami.php");

curl_setopt($ch2, CURLOPT_HEADER, 0);

// 创建批处理cURL句柄

$mh = curl_multi_init();

// 增加2个句柄

curl_multi_add_handle($mh,$ch1);

curl_multi_add_handle($mh,$ch2);

$active = null;

// 执行批处理句柄

do {

$mrc = curl_multi_exec($mh, $active);

} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active && $mrc == CURLM_OK) {

if (curl_multi_select($mh) != –1) {

do {

$mrc = curl_multi_exec($mh, $active);

} while ($mrc == CURLM_CALL_MULTI_PERFORM);

}

}

// 关闭全部句柄

curl_multi_remove_handle($mh, $ch1);

curl_multi_remove_handle($mh, $ch2);

curl_multi_close($mh);

使用strace观察一下:

strace -tt php multi_curl.php

connect(3,{sa_family=AF_INET,sin_port=htons(80), sin_addr=inet_addr("66.147.244.189")}, 16) = -1 EINPROGRESS (Operation now in progress)

poll([{fd=3, events=POLLOUT}], 1, 0)    = 0

虽然是异步,这里还是立即检查了一下是否已经连接成功;但是这种检查也是非阻塞的(看poll的第三个参数)。如果connect连接的是本地端口,poll检查的时候连接就已经是成功的了。 如(10.55.38.14是本机):

connect(4, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("10.55.38.14")}, 16) = -1 EINPROGRESS (Operation now in progress)

poll([{fd=4, events=POLLOUT, revents=POLLOUT}], 1, 0) = 1

——————————————

下面这篇文章写的并不好,仅作学习之用:

这里关键是socket_select的用法了;

另:

1. 当阻塞方式connect的时候,设置连接超时时间是通过设置SO_SNDTIMEO来实现的,如:

socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array(‘sec’ => 3, ‘usec’ => 0));

设置超时时间为3s;

2. 对于非阻塞方式的connect,连接的超时时间不是在socket上设置的,而是自己控制循环的时间

multi_connect.php

$arrTarget = array(

array("host"=>"10.55.38.61", "port"=>80),

array("host"=>"66.147.244.18", "port"=>80),

array("host"=>"10.55.38.63", "port"=>82),

);

$arrResult = multi_connect($arrTarget);

print_r($arrResult);

exit;

function multi_connect($arrTarget) {

$arrSocket = array();

foreach($arrTarget as $key=>$pair) {

$socket  = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_set_nonblock($socket);

@socket_connect($socket, $pair["host"], $pair["port"]);

$arrSocket[$key] = $socket;

}

$arrLeft = $arrSocket;

$arrSocketWrite = $arrSocket;

$arrSocketRead = null;

$arrExcept = array();

$all = count($arrTarget);

$arrOk = array();

$timeout = 5;

$oritimeout = $timeout;

while($all > 0 && $timeout > 0) {

$time_start = time();

$done = socket_select($arrSocketRead, $arrSocketWrite,$arrExcept,$timeout);

$timeout -= (time() – $time_start);

if ($done <= 0) {

//error or timeout

echo "Timeout $oritimeout(s)n";

break;

}

$all -= $done;

foreach($arrSocketWrite as $key=>$val) {

$arrOk[$key] = $val;

}

$arrLeft = array_diff($arrLeft, $arrSocketWrite);

echo "n—-connect ok:——————–n";

print_r($arrSocketWrite);

echo "n—-except:——————–n";

print_r($arrExcept);

echo "n–left:———————-n";

print_r($arrSocketWrite);

echo "n====================================n";

$arrSocketWrite = $arrLeft;

}

return $arrOk;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值