0

0

php socket实现的聊天室代码分享,socket聊天室_PHP教程

php中文网

php中文网

发布时间:2016-07-13 10:20:44

|

1204人浏览过

|

来源于php中文网

原创

熊猫论文
熊猫论文

AI学术写作优化工具,提供AI降重、查重检测、论文润色等服务。

下载

php socket实现的聊天室代码分享,socket聊天室

/**
* patServer
* PHP socket server base class
* Events that can be handled:
*  * onStart
*  * onConnect
*  * onConnectionRefused
*  * onClose
*  * onShutdown
*  * onReceiveData
*
* @version 1.1
* @author  Stephan Schmidt <schst@php-tools.de>
* @package patServer
*/
class patServer {
/**
* information about the project
* @var array $systemVars
*/
var $systemVars  = array(
  "appName"  => "patServer",
  "appVersion"  => "1.1",
  "author"  => array("Stephan Schmidt <schst@php-tools.de>", )
  );

/**
* port to listen
* @var integer  $port
*/
  var $port  = 10000;

/**
* domain to bind to
* @var string $domain
*/
  var $domain  = "localhost";

/**
* maximum amount of clients
* @var integer $maxClients
*/
  var $maxClients = -1;

/**
* buffer size for socket_read
* @var integer $readBufferSize
*/
  var $readBufferSize  = 128;

/**
* end character for socket_read
* @var integer $readEndCharacter
*/
  var $readEndCharacter = "\n";

/**
* maximum of backlog in queue
* @var integer $maxQueue
*/
  var $maxQueue = 500;

/**
* debug mode
* @var boolean $debug
*/
  var $debug  = true;

/**
* debug mode
* @var string $debugMode
*/
  var $debugMode = "text";

/**
* debug destination (filename or stdout)
* @var string $debugDest
*/
  var $debugDest = "stdout";

/**
* empty array, used for socket_select
* @var array $null
*/
  var $null  = array();

/**
* all file descriptors are stored here
* @var array $clientFD
*/
  var $clientFD = array();

/**
* needed to store client information
* @var array $clientInfo
*/
  var $clientInfo = array();

/**
* needed to store server information
* @var array $serverInfo
*/
  var $serverInfo = array();

/**
* amount of clients
* @var integer  $clients
*/
  var $clients = 0;

/**
* create a new socket server
*
* @access public
* @param string  $domain  domain to bind to
* @param integer  $port  port to listen to
*/
function patServer( $domain = "localhost", $port = 10000 )
{
  $this->domain = $domain;
  $this->port  = $port;

  $this->serverInfo["domain"]     = $domain;
  $this->serverInfo["port"]     = $port;
  $this->serverInfo["servername"]   = $this->systemVars["appName"];
  $this->serverInfo["serverversion"] = $this->systemVars["appVersion"];

  set_time_limit( 0 );
}

/**
* set maximum amount of simultaneous connections
*
* @access public
* @param int $maxClients
*/
function setMaxClients( $maxClients )
{
  $this->maxClients = $maxClients;
}

/**
* set debug mode
*
* @access public
* @param mixed $debug [text|htmlfalse]
* @param string $dest destination of debug message (stdout to output or filename if log should be written)
*/
function setDebugMode( $debug, $dest = "stdout" )
{
  if( $debug === false )
  {
  $this->debug = false;
  return true;
  }

  $this->debug  = true;
  $this->debugMode = $debug;
  $this->debugDest = $dest;
}

/**
* start the server
*
* @access public
* @param int $maxClients
*/
function start()
{
  $this->initFD = @socket_create( AF_INET, SOCK_STREAM, 0 );
  if( !$this->initFD )
  die( "patServer: Could not create socket." );

  // adress may be reused
  socket_setopt( $this->initFD, SOL_SOCKET, SO_REUSEADDR, 1 );

  // bind the socket
  if( !@socket_bind( $this->initFD, $this->domain, $this->port ) )
  {
  @socket_close( $this->initFD );
  die( "patServer: Could not bind socket to ".$this->domain." on port ".$this->port." ( ".$this->getLastSocketError( $this->initFd )." )." );
  }

  // listen on selected port
  if( !@socket_listen( $this->initFD, $this->maxQueue ) )
  die( "patServer: Could not listen ( ".$this->getLastSocketError( $this->initFd )." )." );

  $this->sendDebugMessage( "Listening on port ".$this->port.". Server started at ".date( "H:i:s", time() ) );

  // this allows the shutdown function to check whether the server is already shut down
  $GLOBALS["_patServerStatus"] = "running";
  // this ensures that the server will be sutdown correctly
  register_shutdown_function( array( $this, "shutdown" ) );

  if( method_exists( $this, "onStart" ) )
  $this->onStart();

  $this->serverInfo["started"] = time();
  $this->serverInfo["status"]  = "running";

  while( true )
  {
  $readFDs = array();
  array_push( $readFDs, $this->initFD );

  // fetch all clients that are awaiting connections
  for( $i = 0; $i < count( $this->clientFD ); $i++ )
   if( isset( $this->clientFD[$i] ) )
   array_push( $readFDs, $this->clientFD[$i] );

  // block and wait for data or new connection
  $ready = @socket_select( $readFDs, $this->null, $this->null, NULL );

  if( $ready === false )
  {
   $this->sendDebugMessage( "socket_select failed." );
   $this->shutdown();
  }

  // check for new connection
  if( in_array( $this->initFD, $readFDs ) )
  {
   $newClient = $this->acceptConnection( $this->initFD );

   // check for maximum amount of connections
   if( $this->maxClients > 0 )
   {
   if( $this->clients > $this->maxClients )
   {
    $this->sendDebugMessage( "Too many connections." );

    if( method_exists( $this, "onConnectionRefused" ) )
    $this->onConnectionRefused( $newClient );

    $this->closeConnection( $newClient );
   }
   }

   if( --$ready <= 0 )
   continue;
  }

  // check all clients for incoming data
  for( $i = 0; $i < count( $this->clientFD ); $i++ )
  {
   if( !isset( $this->clientFD[$i] ) )
   continue;

   if( in_array( $this->clientFD[$i], $readFDs ) )
   {
   $data = $this->readFromSocket( $i );

   // empty data => connection was closed
   if( !$data )
   {
    $this->sendDebugMessage( "Connection closed by peer" );
    $this->closeConnection( $i );
   }
   else
   {
    $this->sendDebugMessage( "Received ".trim( $data )." from ".$i );

    if( method_exists( $this, "onReceiveData" ) )
    $this->onReceiveData( $i, $data );
   }
   }
  }
  }
}

/**
* read from a socket
*
* @access private
* @param integer $clientId internal id of the client to read from
* @return string $data  data that was read
*/
function readFromSocket( $clientId )
{
  // start with empty string
  $data  = "";

  // read data from socket
  while( $buf = socket_read( $this->clientFD[$clientId], $this->readBufferSize ) )
  {
  $data .= $buf;

  $endString = substr( $buf, - strlen( $this->readEndCharacter ) );
  if( $endString == $this->readEndCharacter )
   break;
  if( $buf == NULL )
   break;
  }

  if( $buf === false )
  $this->sendDebugMessage( "Could not read from client ".$clientId." ( ".$this->getLastSocketError( $this->clientFD[$clientId] )." )." );

  return $data;
}

/**
* accept a new connection
*
* @access public
* @param resource &$socket socket that received the new connection
* @return int  $clientID internal ID of the client
*/
function acceptConnection( &$socket )
{
  for( $i = 0 ; $i <= count( $this->clientFD ); $i++ )
  {
  if( !isset( $this->clientFD[$i] ) || $this->clientFD[$i] == NULL )
  {
   $this->clientFD[$i] = socket_accept( $socket );
   socket_setopt( $this->clientFD[$i], SOL_SOCKET, SO_REUSEADDR, 1 );
   $peer_host = "";
   $peer_port = "";
   socket_getpeername( $this->clientFD[$i], $peer_host, $peer_port );
   $this->clientInfo[$i] = array(
       "host"  => $peer_host,
       "port"  => $peer_port,
       "connectOn" => time()
       );
   $this->clients++;

   $this->sendDebugMessage( "New connection ( ".$i." ) from ".$peer_host." on port ".$peer_port );

   if( method_exists( $this, "onConnect" ) )
   $this->onConnect( $i );
   return $i;
  }
  }
}

/**
* check, whether a client is still connected
*
* @access public
* @param integer $id client id
* @return boolean $connected true if client is connected, false otherwise
*/
function isConnected( $id )
{
  if( !isset( $this->clientFD[$id] ) )
  return false;
  return true;
}

/**
* close connection to a client
*
* @access public
* @param int $clientID internal ID of the client
*/
function closeConnection( $id )
{
  if( !isset( $this->clientFD[$id] ) )
  return false;

  if( method_exists( $this, "onClose" ) )
  $this->onClose( $id );

  $this->sendDebugMessage( "Closed connection ( ".$id." ) from ".$this->clientInfo[$id]["host"]." on port ".$this->clientInfo[$id]["port"] );

  @socket_close( $this->clientFD[$id] );
  $this->clientFD[$id] = NULL;
  unset( $this->clientInfo[$id] );
  $this->clients--;
}

/**
* shutdown server
*
* @access public
*/
function shutDown()
{
  if( $GLOBALS["_patServerStatus"] != "running" )
  exit;
  $GLOBALS["_patServerStatus"] = "stopped";

  if( method_exists( $this, "onShutdown" ) )
  $this->onShutdown();

  $maxFD = count( $this->clientFD );
  for( $i = 0; $i < $maxFD; $i++ )
  $this->closeConnection( $i );

  @socket_close( $this->initFD );

  $this->sendDebugMessage( "Shutdown server." );
  exit;
}

/**
* get current amount of clients
*
* @access public
* @return int $clients amount of clients
*/
function getClients()
{
  return $this->clients;
}

/**
* send data to a client
*
* @access public
* @param int  $clientId ID of the client
* @param string $data  data to send
* @param boolean $debugData flag to indicate whether data that is written to socket should also be sent as debug message
*/
function sendData( $clientId, $data, $debugData = true )
{
  if( !isset( $this->clientFD[$clientId] ) || $this->clientFD[$clientId] == NULL )
  return false;

  if( $debugData )
  $this->sendDebugMessage( "sending: \"" . $data . "\" to: $clientId" );

  if( !@socket_write( $this->clientFD[$clientId], $data ) )
  $this->sendDebugMessage( "Could not write '".$data."' client ".$clientId." ( ".$this->getLastSocketError( $this->clientFD[$clientId] )." )." );
}

/**
* send data to all clients
*
* @access public
* @param string $data  data to send
* @param array $exclude client ids to exclude
*/
function broadcastData( $data, $exclude = array(), $debugData = true )
{
  if( !empty( $exclude ) && !is_array( $exclude ) )
  $exclude = array( $exclude );

  for( $i = 0; $i < count( $this->clientFD ); $i++ )
  {
  if( isset( $this->clientFD[$i] ) && $this->clientFD[$i] != NULL && !in_array( $i, $exclude ) )
  {
   if( $debugData )
   $this->sendDebugMessage( "sending: \"" . $data . "\" to: $i" );

   if( !@socket_write( $this->clientFD[$i], $data ) )
   $this->sendDebugMessage( "Could not write '".$data."' client ".$i." ( ".$this->getLastSocketError( $this->clientFD[$i] )." )." );
  }
  }
}

/**
* get current information about a client
*
* @access public
* @param int  $clientId ID of the client
* @return array $info  information about the client
*/
function getClientInfo( $clientId )
{
  if( !isset( $this->clientFD[$clientId] ) || $this->clientFD[$clientId] == NULL )
  return false;
  return $this->clientInfo[$clientId];
}

/**
* send a debug message
*
* @access private
* @param string $msg message to debug
*/
function sendDebugMessage( $msg )
{
  if( !$this->debug )
  return false;

  $msg = date( "Y-m-d H:i:s", time() ) . " " . $msg;

  switch( $this->debugMode )
  {
  case "text":
   $msg = $msg."\n";
   break;
  case "html":
   $msg = htmlspecialchars( $msg ) . "<br />\n";
   break;
  }

  if( $this->debugDest == "stdout" || empty( $this->debugDest ) )
  {
  echo $msg;
  flush();
  return true;
  }

  error_log( $msg, 3, $this->debugDest );
  return true;
}

/**
* return string for last socket error
*
* @access public
* @return string $error last error
*/
function getLastSocketError( &$fd )
{
  $lastError = socket_last_error( $fd );
  return "msg: " . socket_strerror( $lastError ) . " / Code: ".$lastError;
}
function onReceiveData($ip,$data){

  $this->broadcastData( $data,array(), true );
}
}


$patServer = new patServer();
$patServer->start();

用php socket制作聊天室

何必自讨苦吃呢?php 制作聊天室,关键技术是页面局部自动刷新。
通过php ajax技术,就可以完美的达到你的要求。
具体原理如下,在网页聊天框,被ajax调用,ajax传递参数一个php页面,这个页面同时调用数据库,将数据库中新内容返回到页面聊天框中。
然后你可以自己调时间了,是20秒访问一次数据库,还是10秒访问一次数据库。
至于php的socket技术,说实话,我接触php 8年了,没碰过。
我想,关键不是用什么技术,关键是解决问题。
希望对你有用。
 

php聊天室中的私聊制作写下代码

php对网络通信的支持不是很好,php的socket虽然支持,但是并发性不好。还是用java的mina框架吧。
 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/864934.htmlTechArticlephp socket实现的聊天室代码分享,socket聊天室 /*** patServer* PHP socket server base class* Events that can be handled:* * onStart* * onConnect* * onConnectionRefused*...

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 生态工具与框架:扩展开发能力
Golang 生态工具与框架:扩展开发能力

《Golang 生态工具与框架》系统梳理 Go 语言在实际工程中的主流工具链与框架选型思路,涵盖 Web 框架、RPC 通信、依赖管理、测试工具、代码生成与项目结构设计等内容。通过真实项目场景解析不同工具的适用边界与组合方式,帮助开发者构建高效、可维护的 Go 工程体系,并提升团队协作与交付效率。

1

2026.02.24

Golang 性能优化专题:提升应用效率
Golang 性能优化专题:提升应用效率

《Golang 性能优化专题》聚焦 Go 应用在高并发与大规模服务中的性能问题,从 profiling、内存分配、Goroutine 调度、GC 机制到 I/O 与锁竞争逐层分析。结合真实案例讲解定位瓶颈的方法与优化策略,帮助开发者建立系统化性能调优思维,在保证代码可维护性的同时显著提升服务吞吐与稳定性。

2

2026.02.24

Golang 面试题精选:高频问题与解答
Golang 面试题精选:高频问题与解答

Golang 面试题精选》系统整理企业常见 Go 技术面试问题,覆盖语言基础、并发模型、内存与调度机制、网络编程、工程实践与性能优化等核心知识点。每道题不仅给出答案,还拆解背后的设计原理与考察思路,帮助读者建立完整知识结构,在面试与实际开发中都能更从容应对复杂问题。

1

2026.02.24

Golang 运行与部署实战:从本地到云端
Golang 运行与部署实战:从本地到云端

《Golang 运行与部署实战》围绕 Go 应用从开发完成到稳定上线的完整流程展开,系统讲解编译构建、环境配置、日志与配置管理、容器化部署以及常见运维问题处理。结合真实项目场景,拆解自动化构建与持续部署思路,帮助开发者建立可靠的发布流程,提升服务稳定性与可维护性。

3

2026.02.24

Golang 疑难杂症解决指南:常见问题排查与优化
Golang 疑难杂症解决指南:常见问题排查与优化

《Golang 疑难杂症解决指南》聚焦开发过程中常见却棘手的问题,从并发模型、内存管理、性能瓶颈到工程化实践逐步拆解。通过真实案例与调试思路,帮助开发者定位问题根因,建立系统化排查方法。不只给出答案,更强调分析路径与工具使用,让你在复杂 Go 项目中具备持续解决问题的能力。

1

2026.02.24

Golang 入门学习路线:从零基础到上手开发
Golang 入门学习路线:从零基础到上手开发

Golang 入门路线涵盖从零到上手的核心路径:首先打牢基础语法与切片等底层机制;随后攻克 Go 的灵魂——接口设计与 Goroutine 并发模型;接着通过 Gin 框架与 GORM 深入 Web 开发实战;最后在微服务与云原生工具开发中进阶,旨在培养具备高性能并发处理能力的后端工程师。

0

2026.02.24

中国研究生招生信息网官方网站入口 研招网网页版在线入口
中国研究生招生信息网官方网站入口 研招网网页版在线入口

中国研究生招生信息网入口(https://yz.chsi.com.cn) 此网站是研究生报名入口的唯一官方网站

95

2026.02.24

苹果官网入口与在线访问指南_中国站点快速直达与iPhone查看方法
苹果官网入口与在线访问指南_中国站点快速直达与iPhone查看方法

本专题汇总苹果官网最新可用入口及中国站点访问方式,涵盖官网直达链接、iPhone官方页面查看方法与常见访问说明,帮助用户快速进入苹果官方网站,便捷了解产品信息与官方服务。

14

2026.02.24

Asianfanfics官网入口与访问指南_AFF官方平台最新登录地址
Asianfanfics官网入口与访问指南_AFF官方平台最新登录地址

本专题系统整理Asianfanfics(AFF)官方网站最新可用入口,涵盖官方平台最新直达地址、官网登录方式及中文访问指引,帮助用户快速、安全地进入AFF平台浏览与使用相关内容。

15

2026.02.24

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 12.4万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号