+ -
当前位置:首页 → 问答吧 → 也发聊天,php之socket实现

也发聊天,php之socket实现

时间:2009-09-26

来源:互联网

本帖最后由 omcmc 于 2009-9-26 21:12 编辑

如果连接不到服务器,请尝试点击下面链接,开启服务器端socket
http://www.lhxyw.com/chat/chatserver.php
[flash]http://www.lhxyw.com/chat/chat.swf[/flash]
[php]
<?php
/**
* CopyRight (c) 2009,SESPHP
* All rights reserved.
*  文件名: 聊天SOCKET
*  摘  要:
*
* @author 星期八 [email protected]
* @version
*
*
* socket_create->socket_bind->socket_listen->socket_accept->socket_read/socket_write
*/
class Socket
{
     static  $_instance;
     private $_address='127.0.0.1';
     private $_port=1024;
     private $_socket_handle=0;
     private $_back_flag=10;
     public  $_error='';
     /**
      * 私有构造函数,防止被new
      * @param <string> $address
      * @param <int> $port
      */
     private function __construct($address,$port)
     {
         //设置超时时间 永不超时
         set_time_limit(0);
         //报告所有错误
         error_reporting(E_ALL);
         //开启缓存
         ob_implicit_flush();
         //地址 端口
         $this->_address    =   $address;
         $this->_port       =   $port;
         //创建socket
         $this->socketCreate();
         //绑定socket
         $this->socketBind();
         //监听socket
         $this->socketListen();
         //处理socket
         $this->socketDeal();
     }
     /**
      * 防止被复制后破坏单一限制
      */
     private function  __clone(){}
     /**
      * @param <string> $address
      * @param <int> $port
      */
     public static function run($address,$port)
     {
         if(!self::$_instance instanceof self)
         {
             self::$_instance=new self($address,$port);
         }
         //返回
         return self::$_instance;
     }
     /**
      * 获得错误信息
      * @return <string>
      */
     public function getError()
     {
         return $this->_error;
     }
     /**
      * 设置错误信息
      */
     private function setError()
     {
         $this->_error=socket_last_error();
         socket_clear_error();
     }
     /**
      * 创建socket
      */
     private function socketCreate()
     {
         $this->_socket_handle=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
         if(!$this->_socket_handle)
         {
             $this->setError();
         }
     }
     /**
      * 绑定socket
      */
     private function socketBind()
     {
         if($this->_error)return;
         
         socket_set_option($this->_socket_handle,SOL_SOCKET,SO_REUSEADDR,1);
         $bind_result=socket_bind($this->_socket_handle,$this->_address,$this->_port);
         if(!$bind_result)
         {
             $this->setError();
         }
     }
     /**
      * 监听socket
      */
     private function socketListen()
     {
         if($this->_error)return;

         $listen_result=socket_listen($this->_socket_handle,$this->_back_flag);
         if(!$listen_result)
         {
             $this->setError();
         }
     }
     /**
      * 处理socket
      */
     private function socketDeal()
     {
        if($this->_error)return;

        $read_sockets=array($this->_socket_handle);
        while(true)
        {
            $changed_sockets=$read_sockets;
            $num_changed_sockets=socket_select($changed_sockets,$write = NULL, $except = NULL, NULL);
            if(!$num_changed_sockets)
            {
                continue;
            }
            foreach($changed_sockets as $socket)
            {
                if($socket==$this->_socket_handle)
                {
                    if (($client = socket_accept($socket)) < 0)
                    {
                        $this->setError();
                        continue;
                    }
                    else
                    {
                        array_push($read_sockets,$client);
                    }
                }
                else
                {
                    //$bytes=socket_recv($socket,$buffer,2048,0);
                    $buffer=socket_read($socket, 2048);
                    //if($bytes==0)
                    if($buffer=='')
                    {
                        error_log($buffer,3,'request.log');
                        $index=array_search($socket,$read_sockets);
                        unset($read_sockets[$index]);
                        socket_close($socket);
                    }
                    else
                    {                        
                        if(strpos($buffer,'policy-file-request'))
                        {
                            $msg ="<cross-domain-policy><allow-access-from domain='*' to-ports='*' /></cross-domain-policy>";
                            socket_write($socket, $msg."\0", strlen($msg."\0"));
                        }
                        else
                        {
                            $allclients=$read_sockets;
                            //删除自身
                            array_shift($allclients);
                            //保留消息
                            $this->recordMessage($buffer);
                            //发送消息
                            $this->sendMessage($allclients,$buffer);
                        }
                    }
                }
            }
        }
     }
     /**
      * 保留用户发用信息
      * @param <string> $buffer
      */
     private function recordMessage($buffer)
     {
          error_log($buffer,3,'txt.log');
     }
     /**
      * 广播信息
      * @param <array> $clients
      * @param <string> $buffer
      */
     private function sendMessage($clients,$buffer)
     {
         foreach($clients as $client)
         {
             socket_write($client,$buffer);
         }
     }
}
?>
[/php]

作者: omcmc   发布时间: 2009-09-26

不错啊。

作者: xyyie   发布时间: 2009-09-26

请问下LZ  , 我用的是手册里的socket 例子稍微改了下. 想实现局域网内的聊天通信.  可是不成功.  我本机倒是可以通信.   IP 地址有用过 '127.0.0.1'  和 我本机局域网Ip 都没有用.   
可否指教下?

作者: zxwo0o   发布时间: 2009-09-26

上面的只是php作了服务器端的socket,客户端是使用actionscript实现的,不知道你客户端是怎么实现的?
如果是flash,请注意flash10的安全沙箱问题,不然是连接不到服务器,我因为这个费了不少苦力
代码已经打包,请到www.lhxyw.com下载

作者: omcmc   发布时间: 2009-09-26

走过,路过,千万不要错过。。。。

作者: lgmy6b99   发布时间: 2009-09-26

客户端是使用actionscript
--客户端还能用其他的实现吗?as不会...

作者: wzwen   发布时间: 2009-09-26

这个很好,先收下

另外,想问下LZ,像SINA直播的那种聊天室。并发量很大,该用什么方法好

我自己写过一个DEMO AJAX+JSON实现的聊天室

PS:还跑你BLOG看了下。。。很好,哈哈

作者: guxiaochuan   发布时间: 2009-09-27

有一個bug , 聊天記錄多了..
scrollbar 不會自動向下拉

作者: kisshe   发布时间: 2009-09-29

嗯哼?flash的为什么不考虑用amfphp?

作者: gently   发布时间: 2009-10-03

楼上的,听说你对socket颇有研究,能赐教一下,如何模拟出一个代理服务器吗?要能截获发出的请求,有点抓包的意思,就是用来替代抓包工具。

作者: xiaochong0302   发布时间: 2009-10-03

flash有一个开源的aflax可以用,server端PHP做并不好,我用python写的,也很简单,目前看来还不错。

作者: 月黑风高   发布时间: 2009-10-05

python做服务器端也不错

作者: omcmc   发布时间: 2009-10-05