php长连接,奏是这么简单

说到长链接大家肯定不陌生,就是复用一个链接持续不断的进行数据交互,它不像那些一夜情似的服务,需要频繁的打开和关闭链接,效率低的同时还增加了业务的复杂度。在裆下很多互联网业务场景都需要长连接的支持,比如:游戏、聊天、信息推送等等等,今天我们就一步一步来揭秘php长连接的玩法。我相信任何一项技术的实施都是因为业务场景的需要,所以这次我们还拿聊天室说事儿。

0x00 初试牛刀

记得以前用php写聊天室还是用polling的方式,毫无疑问,一提到polling,肯定会有人说long polling,没错!long polling也很不错,但在nginx+fpm上面玩这个多少有些费劲,毕竟一个请求需要占一个php进程(就算是用apache+php_mod,也需要一个请求一个线程),所以要是几个人随便玩玩还行,一旦放到线上人多起来,这基本就废了。所以还是采用polling的方式,这样不会阻塞进程,并且一个请求能立即得到响应,但是带来的新问题是需要不停的向服务器发送请求,而且随着间隔的时间越大导致消息延迟就越大。

0x01 华丽变身

在经历了上面那种一秒一小卡,三秒一大卡的场面!再也看不下去了,于是决定变身为真正的男人,哦不对,应该是真正的长连接。去他妈的polling, 去他妈的long polling,去他妈的webserver,统统靠边站,让flash socket(或者说websocket)来统治这个世界!开始了真正意义上的长连接之旅。要玩长连接总是少不了跟socket打交道吧,作为世界上最好的语言(没有之一),socket的封装自然是少不了滴。抄起socket_***就开干,于是就有了下面这一托代码,长连接是吧?延迟是吧?socket是吧?汤药费是吧?so easy....


  1. $sfd = socket_create(AF_INET, SOCK_STREAM, 0); 
  2.  
  3. socket_bind($sfd, "0.0.0.0", 1234); 
  4.  
  5. socket_listen($sfd, 511); 
  6.  
  7. socket_set_option($sfd, SOL_SOCKET, SO_REUSEADDR, 1); 
  8.  
  9. socket_set_nonblock($sfd); 
  10.  
  11. $rfds = array($sfd); 
  12.  
  13. $wfds = array(); 
  14.  
  15. do{ 
  16.  
  17.     $rs = $rfds; 
  18.  
  19.     $ws = $wfds; 
  20.  
  21.     $es = array(); 
  22.  
  23.     $ret = socket_select($rs, $ws, $es, 3); 
  24.  
  25.      
  26.  
  27.     //read event 
  28.  
  29.     foreach($rs as $fd){ 
  30.  
  31.         if($fd == $sfd){ 
  32.  
  33.             $cfd = socket_accept($sfd); 
  34.  
  35.             socket_set_nonblock($cfd); 
  36.  
  37.             $rfds[] = $cfd; 
  38.  
  39.             echo "new client coming, fd=$cfd\n"; 
  40.  
  41.         }else{ 
  42.  
  43.             $msg = socket_read($fd, 1024); 
  44.  
  45.             if($msg <= 0){ 
  46.  
  47.                 //close 
  48.  
  49.             }else{ 
  50.  
  51.                 //recv msg 
  52.  
  53.                 echo "on message, fd=$fd data=$msg\n"; 
  54.  
  55.             } 
  56.  
  57.         } 
  58.  
  59.     } 
  60.  
  61.      
  62.  
  63.     //write event 
  64.  
  65.     foreach($ws as $fd){ 
  66.  
  67.         socket_write($fd, ........); 
  68.  
  69.     } 
  70.  
  71.      
  72.  
  73. }while(true); 

0x02 登峰造极

从玩socket的那天起,google就轻言细语的跟我说,高并发下的select不要用啊,效率底啊,win要用iocp啊, linux要用epoll啊,blablablabla...哦!好吧,既然google都这么说了,我也不能跟他老人家较真不是,又一次决定(为什么要说又呢?)要听google话,把epoll搞起来,可总不能自己写啊?像我这么懒的人还是整个扩展好了,libevent走你!经过疯狂的编(co)码(py),神作终于出山,具体能有多高效,能撑多少并发,不造,反正没用select了,我奏是屌!


  1. $sfd = stream_socket_server ('tcp://0.0.0.0:1234', $errno, $errstr); 
  2.  
  3. stream_set_blocking($sfd, 0); 
  4.  
  5. $base = event_base_new(); 
  6.  
  7. $event = event_new(); 
  8.  
  9. event_set($event, $sfd, EV_READ  EV_PERSIST, 'ev_accept', $base); 
  10.  
  11. event_base_set($event, $base); 
  12.  
  13. event_add($event); 
  14.  
  15. event_base_loop($base); 
  16.  
  17. function ev_accept($socket, $flag, $base) 
  18.  
  19.  
  20.     $connection = stream_socket_accept($socket); 
  21.  
  22.     stream_set_blocking($connection, 0); 
  23.  
  24.     $buffer = event_buffer_new($connection, 'ev_read', NULL, 'ev_error',  $connection);     
  25.  
  26.     event_buffer_base_set($buffer, $base); 
  27.  
  28.     event_buffer_timeout_set($buffer, 30, 30); 
  29.  
  30.     event_buffer_watermark_set($buffer, EV_READ, 0, 0xffffff); 
  31.  
  32.     event_buffer_priority_set($buffer, 10); 
  33.  
  34.     event_buffer_enable($buffer, EV_READ  EV_PERSIST); 
  35.  
  36.  
  37. function ev_error($buffer, $error, $connection) 
  38.  
  39.  
  40.     event_buffer_disable($buffer, EV_READ  EV_WRITE);                 
  41.  
  42.     event_buffer_free($buffer);                 
  43.  
  44.     fclose($connection);                 
  45.  
  46.  
  47. function ev_read($buffer, $connection) 
  48.  
  49.  
  50.     $read = event_buffer_read($buffer, 256); 
  51.  
  52.     //do something.... 
  53.  

0x03 绝处逢生

随着人数的增长,并发的提升,单个进程已经满足不了需求了,田伯光的故事告诉我们,单挑是斗不过群P的,咋整?俗话说,大事化小,小事化,停!!别化了,再化就没了。拆吧,把单进程拆成多进程,可是拆完之后又面临新的问题,进程间通信、负载均衡、session唯一等。既然已经提出这样的问题,肯定是有解决方案,现成的就有扩展和库来解决这个事,比如:swoole,workerman等?相比之下swoole更屌一些,性、功能,呃!好像这样简写不太雅观,好吧,性能和功能更屌一些(桶哥,请原谅我的无聊~)。。。。等一下!!!但是,我们在使用php来开发web的时候,也没有使用webserver相关的库来做开发对不对?咱只是简单的echo而已。这些繁杂的事都交给了nginx或者是apache,是他们义无反顾的顶在前面,让我们可以专心写逻辑。写web我们只需要简单的配置nginx和fpm就好了,那写socket服务呢?我们为什么不能像nginx+fpm一样简单配置就好了呢??当然能,必须能。。。。。看这个剧情怕是广告要来了。。。

0x04 出其不意

写socket服务不比写web高级,都是打码,都是完成需求,通信那层都是固定的,只不过一个由nginx完成,另一个由自己完成。。可是现在不需要自己完成了,类似nginx+fpm的方案,fooking+fpm=php长连接,gateway用于承载连接,router用于转发消息,进程间通信?负载均衡?session唯一?so easy..


  1. $sid = $_SERVER['SESSIONID'];//这是sessionid 
  2.  
  3. $data = file_get_contents("php://input");//这样就能拿到请求内容了 
  4.  
  5. //想要返回消息只需要两步 
  6.  
  7. header('Content-Length: 11');//返回给客户端字节数 
  8.  
  9. echo "hello world"; 
  10.  
  11. //想要给别的用户发消息 
  12.  
  13. include 'api.php'; 
  14.  
  15. $router = new RouterClient('router host', 'router port'); 
  16.  
  17. $router->sendMsg(用户sessionid, "fuck you"); 
  18.  
  19. //想要给所有人要消息 
  20.  
  21. $router->sendAllMsg("fuck all"); 
  22.  
  23. //想给指定组发消息(类似redis的pub/sub) 
  24.  
  25. $router->publish("channel name", "fuck all"); 

项目地址: http://git.oschina.net/scgywx/fooking

文档地址(不定期更新):http://my.oschina.net/scgywx/blog/465186 

 

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索socket
, 链接
, 长连接
, 消息
, cfd
, oschina
, 一个
, Polling
, socket消息推送
, http长连接
socket长连接
简单的柳琴演奏曲、简单爱 伴奏、简单的吉他独奏、爱很简单伴奏、没那么简单伴奏,以便于您获取更多的相关知识。

时间: 2024-12-09 14:48:41

php长连接,奏是这么简单的相关文章

PHP 长连接,奏是这么简单

说到长链接大家肯定不陌生,就是复用一个链接持续不断的进行数据交互,它不像那些一夜情似的服务,需要频繁的打开和关闭链接,效率低的同时还增加了业务的复杂度.在裆下很多互联网业务场景都需要长连接的支持,比如:游戏.聊天.信息推送等等等,今天我们就一步一步来揭秘php长连接的玩法.我相信任何一项技术的实施都是因为业务场景的需要,所以这次我们还拿聊天室说事儿. 0x00 初试牛刀 记得以前用php写聊天室还是用polling的方式,毫无疑问,一提到polling,肯定会有人说long polling,没错

基于流模式长连接的简单实现

基于流模式的长连接我们可以做很多事情,比方说在局域网内,我们建立这种模式,可以时时传输数据,而不用每次传输数据是创建socket,传输完后,关闭socket.可以减少创建销毁socket的时间. 基于流模式的下,数据一直在发送,我们需要知道,每次发送数据量,所以常见的方式时,我们在发送数据时,指定此次发送数据的长度,服务器读取流数据时,先读取数据长度,然后再按长度读取此次发送的数据. 我使用select复用IO机制实现了一个简单的client,server机制,希望对初学者有帮助 客户端代码:

Delphi中多进程解决datasnap支持的tcp长连接数量少的问题

对于实时采集数据的项目,应用场景比如是这样的:5000客户端,每个客户端每隔500MS要给服务器上传一次数据. 大家知道,像INDY这种阻塞型的通信控件,所能支持的TCP长连接的一般地不能超过1000的数量(如果想要维持稳定运行的话). 原因是大家都晓得的,阻塞方式会为每一个SOCKET连接创建一个新的线程为之服务,而WINDOWS单个进程理论上允许最多的线程数量是2048个, 实际当中要少得多才行. 有人说可以用WINDOWS的IOCP通信模型解决,诚然!但IOCP编程过于复杂. 有人说,可以

《MySQL DBA修炼之道》——1.5 长连接、短连接、连接池

1.5 长连接.短连接.连接池 当数据库服务器和客户端位于不同的主机时,就需要建立网络连接来进行通信.客户端必须使用数据库连接来发送命令和接收应答.数据.通过提供给客户端数据库的驱动指定连接字符串后,客户端就可以和数据库建立连接了.可以查阅程序语言手册来获知通过何种方式使用短连接.长连接.1.5.1 短连接 短连接是指程序和数据库通信时需要建立连接,执行操作后,连接关闭.短连接简单来说就是每一次操作数据库,都要打开和关闭数据库连接,基本步骤是:连接→数据传 输→关闭连接. 在慢速网络下使用短连接

TCP的长连接和短连接

TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层. 在网络层有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议. 在传输层中有TCP协议与UDP协议. 在应用层有FTP.HTTP.TELNET.SMTP.DNS等协议. 长连接与短连接 所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持.  短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此

Web 通信 之 长连接、长轮询(long polling)

基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易懂的话来说,就是客户端不停的向服务器发送请求以获取最新的数据信息.这里的"不停"其实是有停止的,只是我们人眼无法分辨是否停止,它只是一种快速的停下然后又立即开始连接而已. 二.长连接.长轮询的应用场景 长连接.长轮询一般应用与WebIM.ChatRoom和一些需要及时交互的网站应用中.其真

android通过mina长连接与服务端通信

问题描述 android通过mina长连接与服务端通信 由于项目要求,android与服务端交互方式通过socket长连接,目前自己已经能够搭建个简单的客户端,并 接收到服务端的消息.现在的问题是在如何在不同的activity中获得messageReceived方法中接收到的消息. 解决方案 你的业务是什么~ 每台理解 你的问题

基于Java Socket的自定义协议,实现Android与服务器的长连接(一)

一.基础知识准备 在正式给大家介绍自定义协议之前,我们先对网络传输和协议解析的相关知识点做一个基本的介绍,尽管这些知识点我们在学校里学过,但难免会有所遗忘,这里先做一个简单的介绍,以便对后文的内容理解更加顺畅. 1. 网络七层协议 OSI的7层从上到下分别是:7 应用层. 6 表示层. 5 会话层. 4 传输层. 3 网络层. 2 数据链路层. 1 物理层;其中高层(即7.6.5.4层)定义了应用程序的功能,下面3层(即3.2.1层)主要面向通过网络的端到端的数据流.应用层常见的协议有:HTTP

socket #-C#SOCKET长连接小数据程序未响应

问题描述 C#SOCKET长连接小数据程序未响应 最近由于业务的需要,Linux系统嵌入式设备往我做的服务程序发送数据. 速度奇慢,而且还是程序无响应.后来自己用C#写了一个客户端用来测试.已经用了线程池,不知道用法对不对.请大家帮忙看下. 服务端: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.N