PHP的Socket网络编程入门指引


Posted in PHP onAugust 11, 2015

什么是TCP/IP、UDP?

         TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
         UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
        这里有一张图,表明了这些协议的关系。

PHP的Socket网络编程入门指引

TCP/IP协议族包括运输层、网络层、链路层。现在你知道TCP/IP与UDP的关系了吧。
Socket在哪里呢?

在图1中,我们没有看到Socket的影子,那么它到底在哪里呢?还是用图来说话,一目了然。

PHP的Socket网络编程入门指引

原来Socket在这里。
Socket是什么呢?

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
你会使用它们吗?

前人已经给我们做了好多的事了,网络间的通信也就简单了许多,但毕竟还是有挺多工作要做的。以前听到Socket编程,觉得它是比较高深的编程知识,但是只要弄清Socket编程的工作原理,神秘的面纱也就揭开了。

一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。 生活中的场景就解释了这工作原理,也许TCP/IP协议族就是诞生于生活中,这也不一定。

PHP的Socket网络编程入门指引

PHP的Socket编程概述
php5.3自带了socket模块,使得php具有socket通信能力,具体api可以参考官方手册:http://php.net/manual/zh/function.socket-create.php, 具体实现跟c非常类似,只是少了内存分配和网络字节序转换这种底层操作

同时,php的pcntl模块和posix模块配合可以实现基本的进程管理、信号处理等操作系统级别的功能。这里有两个非常关键的函数,pcntl_fork()和posix_setsid()。fork()一个进程,则表示创建了一个运行进程的副本,副本被认为是子进程,而原始进程被认为是父进程。当fork()运行之后,则可以脱离启动它的进程和终端控制等,也意味着父进程可以自由退出。pcntl_fork()返回值,-1表示执行失败,0表示在子进程中,大于0表示在父进程中。setsit(),它首先使新进程成为一个新会话的“领导者”,最后使进程不再控制终端。这也是成为守护进程最关键一步,这意味着,不会随着终端关闭而强制退出进程。对于一个不会被中断的常驻进程来说,这是很关键的一步。进行最后一次fork(),这一步不是必须的,但通常都这么做,它最大的意义是防止获得控制终端

什么是守护进程?一个守护进程通常被认为是一个不对终端进行控制的后台任务。它有三个很明显的特征:

  1.     在后台运行
  2.     与启动他的进程脱离
  3.     无须终端控制

最常见的实现方法:fork() -> setsid() -> fork(), 代码里run_server()方法实现了守护进程。

server端socket监听代码

<?php 
   
  // 接受客户端请求,回复固定的响应内容 
  function server_listen_socket ($address, $port) 
  { 
    $buffer = "Msg from wangzhengyi server, so kubi..."; 
    $len = strlen($buffer); 
     
    // create, bind and listen to socket 
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 
    if (! $socket) { 
      echo "failed to create socket:" . socket_strerror($socket) . "\n"; 
      exit(); 
    } 
     
    $bind_flag = socket_bind($socket, $address, $port); 
    if (! $bind_flag) { 
      echo "failed to bind socket:" . socket_strerror($bind_flag) . "\n"; 
      exit(); 
    } 
     
    $backlog = 20; 
    $listen_flag = socket_listen($socket, $backlog); 
    if (! $listen_flag) { 
      echo "failed to listen to socket:" . socket_strerror($listen_flag) . "\n"; 
      exit(); 
    } 
     
    echo "waiting for clients to connect\n"; 
     
    while (1) { 
      if (($accept_socket = socket_accept($socket)) == FALSE) { 
        continue; 
      } else { 
        socket_write($accept_socket, $buffer, $len); 
        socket_close($accept_socket); 
      } 
    } 
  } 
   
  function run_server () 
  { 
    $pid1 = pcntl_fork(); 
    if ($pid1 == 0) { 
      // first child process 
       
      // 守护进程的一般流程:fork()->setsid()->fork() 
      posix_setsid(); 
       
      if (($pid2 = pcntl_fork()) == 0) { 
        $address = "192.168.1.71"; 
        $port = "8767"; 
        server_listen_socket($address, $port); 
      } else { 
        // 防止获得控制终端 
        exit(); 
      } 
    } else { 
      // wait for first child process exit 
      pcntl_wait($status); 
    } 
  } 
   
  // server守护进程 
  run_server();

运行效果
启动服务器端socket进程,看是否在后台运行,效果如图:

PHP的Socket网络编程入门指引

客户端访问,可以通过浏览器或者curl访问,这里直接用curl访问了

PHP的Socket网络编程入门指引

PHP 相关文章推荐
php下防止单引号,双引号在接受页面转义的设置方法
Sep 25 PHP
PHP 文件上传功能实现代码
Jun 24 PHP
PHP中for与foreach的区别分析
Mar 09 PHP
php学习笔记 [预定义数组(超全局数组)]
Jun 09 PHP
php-cli简介(不会Shell语言一样用Shell)
Jun 03 PHP
php sybase_fetch_array使用方法
Apr 15 PHP
详解php设置session(过期、失效、有效期)
Nov 12 PHP
Thinkphp微信公众号支付接口
Aug 04 PHP
PHP Cookie学习笔记
Aug 23 PHP
php array_map使用自定义的函数处理数组中的每个值
Oct 26 PHP
PHP中十六进制颜色与RGB颜色值互转的方法
Mar 18 PHP
PHP快速导出百万级数据到CSV或者EXCEL文件
Nov 27 PHP
php实现的农历算法实例
Aug 11 #PHP
PHP发送短信代码分享
Aug 11 #PHP
php实现可逆加密的方法
Aug 11 #PHP
PHP实现获取某个月份周次信息的方法
Aug 11 #PHP
PHP实现删除字符串中任何字符的函数
Aug 11 #PHP
详解php的socket通信
Aug 11 #PHP
Java中final关键字详解
Aug 10 #PHP
You might like
PHP开发需要注意的安全问题
2010/09/01 PHP
PHP+Mysql日期时间如何转换(UNIX时间戳和格式化日期)
2012/07/15 PHP
什么是PEAR?什么是PECL?PHP中两个容易混淆的概念解释
2015/07/01 PHP
PHP实现无限级分类(不使用递归)
2015/10/22 PHP
php实现的三个常用加密解密功能函数示例
2017/11/06 PHP
PHP+MySQL高并发加锁事务处理问题解决方法
2018/04/30 PHP
javascript下对于事件、事件流、事件触发的顺序随便说说
2010/07/17 Javascript
jQuery UI Datepicker length为空或不是对象错误的解决方法
2010/12/19 Javascript
jquery 获取标签名(tagName)示例代码
2013/07/11 Javascript
基于JQuery实现滚动到页面底端时自动加载更多信息
2014/01/31 Javascript
nodejs 整合kindEditor实现图片上传
2015/02/03 NodeJs
分享js粘帖屏幕截图到web页面插件screenshot-paste
2020/08/21 Javascript
微信小程序 在Chrome浏览器上运行以及WebStorm的使用
2016/09/27 Javascript
微信小程序 用户数据解密详细介绍
2017/01/09 Javascript
如何使用Bootstrap 按钮实例详解
2017/03/29 Javascript
js时间戳与日期格式之间转换详解
2017/12/11 Javascript
Javascript中从学习bind到实现bind的过程
2018/01/05 Javascript
JavaScript中使用import 和require打包后实现原理分析
2018/03/07 Javascript
jQuery中$原理实例分析
2018/08/13 jQuery
Vue.js构建你的第一个包并在NPM上发布的方法步骤
2019/05/01 Javascript
微信小程序实现获取用户信息并存入数据库操作示例
2019/05/07 Javascript
详解Vue项目引入CreateJS的方法(亲测可用)
2019/05/30 Javascript
koa2的中间件功能及应用示例
2020/03/05 Javascript
vue 项目引入echarts 添加点击事件操作
2020/09/09 Javascript
python3模拟百度登录并实现百度贴吧签到示例分享(百度贴吧自动签到)
2014/02/24 Python
Python字符串处理之count()方法的使用
2015/05/18 Python
win7 x64系统中安装Scrapy的方法
2018/11/18 Python
5分钟 Pipenv 上手指南
2018/12/20 Python
CSS3实现类似翻书效果的过渡动画的示例代码
2019/09/06 HTML / CSS
使用html2canvas实现浏览器截图的示例代码
2018/01/26 HTML / CSS
人力资源管理专业应届生求职信
2014/04/24 职场文书
2015年老干部工作总结
2015/04/23 职场文书
2015年超市员工工作总结
2015/05/04 职场文书
搞笑婚礼主持词开场白
2015/11/24 职场文书
《打电话》教学反思
2016/02/22 职场文书
MySQL数据库实验之 触发器和存储过程
2022/06/21 MySQL