利用PHP如何实现Socket服务器


Posted in PHP onSeptember 23, 2015

socket服务器的工作方式是这样的,不间断地运行以等待客户端的连接。一旦客户端连接上了,服务器就会将它添加到客户名单中,然后开始等待来自客户端的消息。

利用PHP如何实现Socket服务器

不要走开,下面是完整的源代码:

// Set time limit to indefinite execution 
set_time_limit (0); 
 
// Set the ip and port we will listen on 
$address = 'localhost'; 
$port = 10000; 
$max_clients = 10; 
 
// Array that will hold client information 
$client = Array(); 
 
// Create a TCP Stream socket 
$sock = socket_create(AF_INET, SOCK_STREAM, 0); 
// Bind the socket to an address/port 
socket_bind($sock, $address, $port) or die('Could not bind to address'); 
// Start listening for connections 
socket_listen($sock); 
 
echo "Waiting for connections...\r\n"; 
 
// Loop continuously 
while (true) { 
// Setup clients listen socket for reading 
$read[0] = $sock; 
for ($i = 0; $i < $max_clients; $i++) { 
 if (isset($client[$i]['sock'])) 
  $read[$i + 1] = $client[$i]['sock']; 
} 
// Set up a blocking call to socket_select() 
if (socket_select($read, $write = NULL, $except = NULL, $tv_sec = 5) < 1) 
 continue; 
/* if a new connection is being made add it to the client array */ 
if (in_array($sock, $read)) { 
 for ($i = 0; $i < $max_clients; $i++) { 
  if (empty($client[$i]['sock'])) { 
  $client[$i]['sock'] = socket_accept($sock); 
  echo "New client connected $i\r\n"; 
  break; 
  } 
  elseif ($i == $max_clients - 1) 
  echo "Too many clients...\r\n"; 
 } 
} // end if in_array 
 
// If a client is trying to write - handle it now 
for ($i = 0; $i < $max_clients; $i++) { // for each client 
 if (isset($client[$i]['sock'])) { 
  if (in_array($client[$i]['sock'], $read)) { 
  $input = socket_read($client[$i]['sock'], 1024); 
  if ($input == null) { 
   echo "Client disconnecting $i\r\n"; 
   // Zero length string meaning disconnected 
   unset($client[$i]); 
  } else { 
   echo "New input received $i\r\n"; 
   // send it to the other clients 
   for ($j = 0; $j < $max_clients; $j++) { 
   if (isset($client[$j]['sock']) && $j != $i) { 
    echo "Writing '$input' to client $j\r\n"; 
    socket_write($client[$j]['sock'], $input, strlen($input)); 
   } 
   } 
   if ($input == 'exit') { 
   // requested disconnect 
   socket_close($client[$i]['sock']); 
   } 
  } 
  } else { 
  echo "Client disconnected $i\r\n"; 
  // Close the socket 
  socket_close($client[$i]['sock']); 
  unset($client[$i]); 
  } 
 } 
} 
} // end while 
// Close the master sockets 
socket_close($sock);

哎呀,乍一看这似乎是一个大工程,但是我们可以先将它分解为几个较小的部分。

第一部分是创建服务器。Lines:2至20。

这部分代码设置了变量、地址、端口、最大客户端和客户端数组。接下来创建socket并将其绑定到我们指定的地址和端口上。

下面我们要做的事情就是执行一个死循环(实际上我们是故意的!)。Lines:22至32。

在这部分代码中我们做的第一步是设置 $read 数组。此数 组包含所有客户端的套接字和我们主服务器的套接字。这个变量稍后会用于select语句:告诉PHP监听来自这些客户端的每一条消息。

socket_select()的最后一个参数告诉我们的服务器在返回值之前最多等待5秒钟。如果它的返回值小于1,那么就表示没有收到任何数据,所以只需要返回循环顶部,继续等待。

脚本的下一个部分,是增加新的客户端到数组中。Lines:33至44。

将新的客户端放置在列表的末尾。检查以确保客户端的数量没有超过我们想要服务器处理的数量。

下面要介绍的代码块相当大,也是服务器的主要部分。当客户端将消息发送到服务器时,就需要这块代码挺身而出来处理。消息可以是各种各样的,断开消息、实际断开——只要是服务器需要处理的消息。Lines:46至末尾。

代码循环通过每个客户端并检查是否收到来自于它们的消息。如果是,获取输入的内容。根据输入来检查这是否是一个断开消息,如果是那就从数组中删除它们,反之,那它就是一个正常的消息,那我们的服务器再次通过所有客户端,并一个一个写信息给他们,跳过发送者。

好了,下面试试创造你自己的聊天服务器吧!

PHP 相关文章推荐
无数据库的详细域名查询程序PHP版(2)
Oct 09 PHP
一个分页的论坛
Oct 09 PHP
php Undefined index的问题
Jun 01 PHP
用PHP的ob_start() 控制您的浏览器cache
Aug 03 PHP
用PHP获取Google AJAX Search API 数据的代码
Mar 12 PHP
如何使用Linux的Crontab定时执行PHP脚本的方法
Dec 19 PHP
php上传中文文件名乱码问题处理方案
Feb 03 PHP
php备份数据库类分享
Apr 14 PHP
php文件操作相关类实例
Jun 18 PHP
jquery不支持toggle()高(新)版本的问题解决
Sep 24 PHP
PHP性能分析工具xhprof的安装使用与注意事项
Dec 19 PHP
Yii2.0 RESTful API 基础配置教程详解
Dec 26 PHP
10个超级有用的PHP代码片段果断收藏
Sep 23 #PHP
Discuz!X中SESSION机制实例详解
Sep 23 #PHP
php中session_id()函数详细介绍,会话id生成过程及session id长度
Sep 23 #PHP
通过修改配置真正解决php文件上传大小限制问题(nginx+php)
Sep 23 #PHP
php实现简单的MVC框架实例
Sep 23 #PHP
php实现的单一入口应用程序实例分析
Sep 23 #PHP
PHP中常见的缓存技术实例分析
Sep 23 #PHP
You might like
php判断输入不超过mysql的varchar字段的长度范围
2011/06/24 PHP
CodeIgniter CLI模式简介
2014/06/17 PHP
destoon调用discuz论坛中带图片帖子的实现方法
2014/08/21 PHP
10个超级有用的PHP代码片段果断收藏
2015/09/23 PHP
PHP7 参数处理机制修改
2021/03/09 PHP
对xmlHttp对象的理解
2011/01/17 Javascript
三级下拉菜单的js实现代码
2011/05/23 Javascript
JQUERY 设置SELECT选中项代码
2014/02/07 Javascript
JavaScript自定义等待wait函数实例分析
2015/03/23 Javascript
jQuery的Scrollify插件实现滑动到页面下一节点
2015/07/05 Javascript
JavaScript脚本库编写的方法
2015/12/09 Javascript
jQuery 局部div刷新和全局刷新方法总结
2016/10/05 Javascript
jQuery使用正则验证15/18身份证的方法示例
2017/04/27 jQuery
JS实现图片点击后出现模态框效果
2017/05/03 Javascript
vue 循环加载数据并获取第一条记录的方法
2018/09/26 Javascript
BootStrap modal实现拖拽功能
2018/12/01 Javascript
Python 编码规范(Google Python Style Guide)
2018/05/05 Python
Python实现统计给定字符串中重复模式最高子串功能示例
2018/05/16 Python
Django中使用Celery的教程详解
2018/08/24 Python
Python实现线性判别分析(LDA)的MATLAB方式
2019/12/09 Python
python 双循环遍历list 变量判断代码
2020/05/04 Python
python打开音乐文件的实例方法
2020/07/21 Python
Python requests上传文件实现步骤
2020/09/15 Python
python实现人性化显示金额数字实例详解
2020/09/25 Python
意大利在线购买隐形眼镜网站:VisionDirect.it
2019/03/18 全球购物
2013年办公室秘书的个人自我鉴定
2013/10/24 职场文书
水果超市创业计划书
2014/01/27 职场文书
给学校建议书范文
2014/05/13 职场文书
三方协议书
2015/01/27 职场文书
幼儿园安全工作总结2015
2015/04/20 职场文书
爱心捐款活动总结
2015/05/09 职场文书
2015年劳动部工作总结
2015/05/23 职场文书
小学教师教学随笔
2015/08/14 职场文书
《打电话》教学反思
2016/02/22 职场文书
python基于tkinter制作无损音乐下载工具
2021/03/29 Python
详解盒子端CSS动画性能提升
2021/05/24 HTML / CSS