博主信息
刘佳俊的博客
博文
11
粉丝
0
评论
3
访问量
6415
积分:2
P豆:51

用php进行socket通讯

2017年07月26日 10:18:24阅读数:242博客 / 刘佳俊的博客 / php进阶

一开始会接触这个php的socket是因为需要用到长连接,去搜一下php的socket。还真的有这个东西。于是就各种看资料,基本摸清了是怎么样的一个情况了。在这里我先描述一下,在上具体的代码。

php的socket通讯呢。是基于TCP上的。有个服务端创建了tcp的连接,然后客户端可以和服务端云运行的那个连接进行通讯。而服务端可以监听到客户端的请求,如发送信息。服务端这个时候也可以再响应数据回去。还是要实践一下才比较熟悉

上php的文档:http://php.net/manual/zh/ref.sockets.php

然后开始先写一个服务端的代码

service.php

<?php
/**
 * Created by PhpStorm.
 * User: LiuJiaJun
 * Date: 2017/7/26
 * Time: 10:56
 */
   $host = '127.0.0.1';//ip地址,这里是本地的
   $port ='2008';//端口号
   $sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);//创建一个socket,还不能用
   if($sock < 0){
       echo "socket_create() 失败的原因".socket_strerror(socket_last_error($sock));
   }
   //将地址和端口绑定到刚创建的socket中
   if($bind = socket_bind($sock,$host,$port)<0){
       echo "socket_create() 失败的原因".socket_strerror(socket_last_error($bind));
   }
   //进行监听,设置的数量是4个
   if($listen = socket_listen($sock,4) <0){
       echo "socket_create() 失败的原因".socket_strerror(socket_last_error($listen));
   }
   $count = 5;//设置五次访问次数
   do{
       $accept = socket_accept($sock);//另一个Socket来处理通信
       if($accept<0){
           echo "socket_accept()失败的原因".socket_strerror(socket_last_error($accept));
           break;
       }else{
           $buf = socket_read($accept,8192);//读取客户端传送的数据
           $response='you send message is:'.$buf;
            //将信息返回给客户端,第三个参数是返回的长度
           $res = socket_write($accept,$response,strlen($response));
           if($res !==false){
               echo 'send message to client is successful';
           }
           if($count--<=0){
               break;
           }
       }
       socket_close($accept);
   }while(true);
   socket_close($sock);

再此说明一下,这个service.php文件应该是通过命令行的形式运行,即php service.php start。如果php命令不可以用,那么就需要在环境变量path那边配置一些你的php信息。先运行service.php,再去访问client.php文件。服务端接受5次请求就会自动关闭,代码上已经实现。

client.php客户端的程序

<?php
/**
 * Created by PhpStorm.
 * User: LiuJiaJun
 * Date: 2017/7/26
 * Time: 11:13
 */
  error_reporting(E_ALL);
  set_time_limit(0);
  $host = '127.0.0.1';
  $port = '2008';
  $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
  if ($socket < 0) {
    echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";
  }
  $result = socket_connect($socket, $host, $port);//连接服务端创建的接口
  if ($result < 0) {
    echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
  }else {
    echo "连接 '$host' 端口 '$port'.'成功'.\n";
  }
   $input = 'hello world';
   if(!socket_write($socket, $input, strlen($input))) {//向服务端写数据
     echo "socket_write() failed: reason: " . socket_strerror($socket) . "\n";
  }else {
     echo "发送到服务器信息的内容为".$input;
  }
   while($output = socket_read($socket, 8192)) {//读取服务端响应的数据
      echo "接受的内容为:",$output;
   }
    socket_close($socket);
    echo "关闭成功\n";

说明一下,client.php可以在网页上运行,只要能解释通php语言就行,但是这个例子也只能做到,你给他发送数据了,它在响应你一个数据,要是这样的话,和寻常的http请求没啥区别。当然也就是针对这个例子来说,我也是尝试用,还不能写出主动发送数据的代码。而且对有些函数还是了解甚少。

服务端运行截图:

服务端.png

客户端运行截图:

客户端.png

当然写到这里就是简单的知道一些socket函数的用法,以及他们之间的通讯而已。有了这些基础就能进一步钻研啦。

关于长连接的有些框架可以使用:

Swoole扩展:

    附上官网地址:http://www.swoole.com/

    附上文档地址:https://wiki.swoole.com/

Workman框架:

    附上官网地址:http://www.workerman.net/

    附上文档地址:https://www.kancloud.cn/walkor/workerman/315110

近段时间有用workman写一些东西,有时间的话在写一篇关于这个的文章吧

socket相关函数:
----------------------------------------------------------------------------------------------
socket_accept() 接受一个Socket连接
socket_bind() 把socket绑定在一个IP地址和端口上
socket_clear_error() 清除socket的错误或者最后的错误代码
socket_close() 关闭一个socket资源
socket_connect() 开始一个socket连接
socket_create_listen() 在指定端口打开一个socket监听
socket_create_pair() 产生一对没有区别的socket到一个数组里
socket_create() 产生一个socket,相当于产生一个socket的数据结构
socket_get_option() 获取socket选项
socket_getpeername() 获取远程类似主机的ip地址
socket_getsockname() 获取本地socket的ip地址
socket_iovec_add() 添加一个新的向量到一个分散/聚合的数组
socket_iovec_alloc() 这个函数创建一个能够发送接收读写的iovec数据结构
socket_iovec_delete() 删除一个已经分配的iovec
socket_iovec_fetch() 返回指定的iovec资源的数据
socket_iovec_free() 释放一个iovec资源
socket_iovec_set() 设置iovec的数据新值
socket_last_error() 获取当前socket的最后错误代码
socket_listen() 监听由指定socket的所有连接
socket_read() 读取指定长度的数据
socket_readv() 读取从分散/聚合数组过来的数据
socket_recv() 从socket里结束数据到缓存
socket_recvfrom() 接受数据从指定的socket,如果没有指定则默认当前socket
socket_recvmsg() 从iovec里接受消息
socket_select() 多路选择
socket_send() 这个函数发送数据到已连接的socket
socket_sendmsg() 发送消息到socket
socket_sendto() 发送消息到指定地址的socket
socket_set_block() 在socket里设置为块模式
socket_set_nonblock() socket里设置为非块模式
socket_set_option() 设置socket选项
socket_shutdown() 这个函数允许你关闭读、写、或者指定的socket
socket_strerror() 返回指定错误号的详细错误
socket_write() 写数据到socket缓存
socket_writev() 写数据到分散/聚合数组

本文参考了:http://www.jb51.net/article/66023.htm的文章,且本人水平有限,不足之处还望海涵。

全部评论

文明上网理性发言,请遵守新闻评论服务协议

条评论
小皮
  • 小皮· 2017-07-26 17:22:303楼
  • 我是第三个评论吗

  • 回复
  • ringa_lee
  • ringa_lee· 2017-07-26 14:34:162楼
  • 第二排,哈哈。 文章不错哈,收藏啦

  • 回复
  • 倾城、一世
  • 倾城、一世· 2017-07-26 13:50:381楼
  • 第一排

  • 回复