玩转PHP网络编程全套阻塞与非阻塞

扯蛋

上一篇我们撸了不咋样的TCPserver,然后还扯了半天的口水,现在呢我们来继续撸客户端

TCPServer

$ip="0.0.0.0";$port=$argv[1];$sockefd=socket_create(AF_INET,SOCK_STREAM,0);socket_bind($sockefd,$ip,$port);socket_listen($sockefd,5);while(1){$connfd=socket_accept($sockefd);if($connfd){socket_write($connfd,"hello,php是世界上是好的语言");while(1){if(($recv=socket_read($connfd,,PHP_BINARY_READ))){socket_write($connfd,"server:$recv");}}}}socket_close($sockefd);socket_close($connfd);TCPClient

$ip=$argv[1];$port=$argv[2];$sockfd=socket_create(AF_INET,SOCK_STREAM,0);socket_connect($sockfd,$ip,$port);while(1){if(($recv=socket_read($sockfd,))){echo$recv;}$data=fread(STDIN,);if($data){socket_write($sockfd,$data,strlen($data));}}socket_close($sockfd);现在我们来分别运行server/client来简单的通信

ok,以上通信没问题

现在用telent工具来折腾下它

启动服务时我们看到客户端与服务器端是可以正常来往通信的,我们看到服务器运行时它是处于accept阻塞进程的。连接服务时客户连接时,accept立马执行同时返回一个TCP连接,并且这个连接通过为5,程序就执行到socket_read处阻塞了,同时我们列出/proc/PID/fd时生成了如下文件当客户发送字符串”hello”时socket_read函数执行并读取到内容及读取的数据长度

以上说了半天,就是在告诉你socket_accept,socket_read,socket_write这些函数是阻塞IO!!!

阻塞IO与非阻塞IO

我觉得光解释不行的,你得撸上代码去体验阻塞IO:执行系统调用时不会立即返回,需要等待就绪事件发生,操作系统会让程序挂起来非阻塞IO:执行系统调用后,程序会立即返回,如果事件没有发生会返回-1,同时会带有出错信息如EAGAIN,EWOULDBLOCK,EINPROGRESS

那我们下面来写一个非阻塞的TCP服务

非阻塞的IO

设置非阻塞的函数ps:在c语言里一般用fcntl去控制文件描述符

socket_set_nonblock($socket);stream_set_blocking(resource$stream,int$mode)

$ip="0.0.0.0";$port=$argv[1];$sockefd=socket_create(AF_INET,SOCK_STREAM,0);socket_bind($sockefd,$ip,$port);socket_listen($sockefd,5);$counter=0;while(1){$counter++;//$sockfd我们最好让它阻塞,不然立马返回的话$connfd可不是资源即连接就会导致socket_set_nonblock报错的$connfd=socket_accept($sockefd);echo"accept\n";//得到客户端连接设置为非阻塞IO模式socket_set_nonblock($connfd);if($connfd){socket_write($connfd,"hello,php是世界上是好的语言");echo"writeonce\n";//要是这里不加while它就跑一次完事了//加上while就是让socket_read一直不停的问有没有数据while(1){if(($recv=socket_read($connfd,,PHP_BINARY_READ))){socket_write($connfd,"server:$recv");}//上面的socket_read不管有没有读取到数据//都立马返回并且执行echo//如果是阻塞模式,则该句就得等上面的socket_read运行了这里才执行,否则就得等,等的结果就是SLEEP,cpu就会干其它事情了echo"不阻塞一直不停的执行socket_read问内核有没有数据\n";sleep(1);}}}socket_close($sockefd);socket_close($connfd);

测试的结果同样的我们不设置为非阻塞模式时,它默认是阻塞IO

往期推荐

玩转PHP网络编程全套之数据接收与发送

玩转PHP网络编程全套之I/O复用

玩转PHP网络编程首篇

预览时标签不可点收录于合集#个上一篇下一篇

转载请注明:http://www.aierlanlan.com/cyrz/484.html