热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PHP编写基本的Socket程序

socket编程需要开启php的socket扩展,我用的电脑是windows,所以这里你只需要打开php.ini文件,找到这一行去掉注释就可以了
告诫年轻人

空想是没有用的,个人的能力来源于每一天的努力,而不是一步登天,不要畏惧任何新的知识,水滴石穿,总有一天会柳暗花明。

我的目的

因为在以后的学习中,我可能会用到网络方面的内容,但同时很多写 PHP 的 coder 都没写过 socket 程序,但是肯定听说过它,也肯定听说过网络编程这个词,所以为了今后的学习,我打算在这里先简单的讲解下相关知识,本篇博文自带实例程序,代码托管在码云(php-socket-base-code:https://gitee.com/obamajs/php-socket-base-code),你只需要下载下来,配置好相关环境,按照说明即可运行。

环境配置

socket 编程需要开启 php 的 socket 扩展,我用的电脑是 windows,所以这里你只需要打开 php.ini 文件,找到这一行去掉注释就可以了

extension=sockets

官方文档

php 的 socket 编程的官方地址为:php socket(https://www.php.net/manual/en/book.sockets.php)

服务端编程

socket 编程遵循一定的编程步骤,这几个步骤缺一不可,客户端和服务端编程有所区别,我们首先来看一下服务端。

创建套接字

套接字属于系统资源,我们首先调用 socket_create 方法(参考官方文档:https://www.php.net/manual/en/function.socket-create.php),调用如下:

$this->socket_handle = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$this->socket_handle) {
      //创建失败抛出异常,socket_last_error获取最后一次socket操作错误码,socket_strerror打印出对应错误码所对应的可读性描述
     throw new Exception(socket_strerror(socket_last_error($this->socket_handle)));
} else {
          echo "create socket successful\n";
}

第一个参数指定了,当前套接字是采用 ipv4 还是 ipv6,如果是前者的话,那么传递 AF_INET,否则 AF_INET6,当然还有一种类型,就是 AF_UNIX,这个暂时不讨论,我们一般选择 AF_INET(ipv6 不是很普及)。

第二个参数,指定了协议的类型,一般选择 TCP 或者是 UDP,TCP 是可靠的流传输(生活当中用的最为广泛,保证了可靠性和安全性),UDP 则不是,这个参数一般选择 TCP。

第三个如果你之前选择了 TCP,那么它就是 SOL_TCP,否则就是 SOL_UDP。

绑定地址和端口号

因为一台主机可能存在多个 ip 地址,所以你需要指定你的 socket 监听的是哪一个,常用的值为 127.0.0.1,或者是监听所有地址 0.0.0.0,那么这里可能有人不明白了,127.0.0.1 和 0.0.0.0 有啥区别呢?127.0.0.1 只是一个回环地址,只能用于本机访问,说白了就是自己玩自己的,因为这个 ip 不对外部开放,所以有人也就无法访问这个地址,所以如果你的服务器地址设置为 127.0.0.1,别人想要访问,只能去屎吧。

0.0.0.0 严格来说不算是一个 ip 地址,它的意思是本机的所有 IP 地址,都是我的,哈哈。

明白了上面这个,我们来看这个调用的代码

if (!socket_bind($this->socket_handle, $this->addr, $this->port)) {
         throw new Exception(socket_strerror(socket_last_error($this->socket_handle)));
    } else {
         echo "bind addr successful\n";
 }

是不是很简单,第一个参数就是 socket_create 返回的结果,第二个参数就是地址了,上面已经说过了,第三个参数是端口号。

监听套接字

经过上面的这些步骤,我们只是创建了一个套接字并且给它绑定了端口号和地址,但是系统怎么知道它是监听套接字呢?所以呢,我们的事情还没有做完,所以我们得告诉它啊,别告诉我你和系统心有灵犀啊!!!

if (!socket_listen($this->socket_handle, $this->back_log)) {
      throw new Exception(socket_strerror(socket_last_error($this->socket_handle)));
  } else {
      echo "socket  listen successful\n";
 }

第二个参数值得说明一哈,请听我细细道来,对于 linux 系统中的每一个进程而言,系统都维护着待处理套接字的队列(先进先出,总得讲个先来后到吧),上层程序处理业务逻辑总得需要时间吧,所以让你你等着你就等着呗。那么这个队列的大小设置为多大呢?它的值就是这第二个参数,那么我是不是可以设置的很大呢?骚年,你想多了吧?不同的系统这个值有所不同,别说我忽悠你,看下面。

The maximum number passed to the backlog parameter highly depends on the underlying platform. On Linux, it is silently truncated to SOMAXCONN. On win32, if passed SOMAXCONN, the underlying service provider responsible for the socket will set the backlog to a maximum reasonable value. There is no standard provision to find out the actual backlog value on this platform.

你也不必关心这个值精确的数据,没有什么意义。

万事俱备,只欠东风

经过上面的一通操作之后,我们可以开始接受来自客户端的连接了,这个函数就更简单了

$client_socket_handle = socket_accept($this->socket_handle);

这个函数的返回值也是一个套接字句柄,所以你可以对它进行读写操作,在当前的实例程序中,我们做的事情很简单,简单到你可以怀疑人生了。

 $client_socket_handle = socket_accept($this->socket_handle);
        if (!$client_socket_handle) {
            echo "socket_accept call failed\n";
            exit(1);
        } else {
            while (true) {
                $bytes_num = socket_recv($client_socket_handle, $buffer, 100, 0);
                if (!$bytes_num) {
                    echo "socket_recv  failed\n";
                    exit(1);
                } else {
                    echo "content from client:" . $buffer . "\n";
                }
            }
        }

读取套接字

以上面的例子为例,我们使用 socket_recv 读取来自客户端的内容,这个函数很简单,函数原型如下

socket_recv ( resource $socket , string &$buf , int $len , int $flags ) : int

读取的内容会在第二个参数返回,第二个参数传递我们想要读取的字符数,第四个参数可以直接设置为 0,该函数的返回值为实际读取的字节数。

客户端编程

客户端相对于服务端来说,就很简单了,流程如下

创建套接字前面已经讲过了,不再详述,客户端只需要连接服务器即可,函数为 socket_create,我们来看一哈在当前的例子中,我们是如何调用的。

if (!socket_connect($this->socket_handle, $this->server_addr, $this->server_port)) {
            echo socket_strerror(socket_last_error($this->socket_handle)) . "\n";
            exit(1);
        } else {
            while (true) {
                $data = fgets(STDIN);
                //如果用户输入quit,那么退出程序
                if (strcmp($data, "quit") == 0) {
                    break;
                }
                socket_write($this->socket_handle, $data);
            }
        }

该函数只需要指定服务器的地址和端口号即可,参数是不是很简单

练习实例

在讲解基本函数调用的时候,我就把自带程序的核心部分,复制出来了,如果要完整的程序,这里是地址(php-socket-base-code:https://gitee.com/obamajs/php-socket-base-code),代码非常简单,再次提醒,这些代码完全是用于给大家讲解基本的 socket 变成操作,为大家以后的学习打下基础,那么如何使用这个例子程序呢?

进入到命令行,开启服务器程序

php TcpServer.php,

打开另外一个命令行界面,

php TcpClient.php,

在客户端界面,输入任何文本,再输入回车,再切换到服务器界面,您将会看到客户端输入的内容

在笔者的电脑上操作实例截图如下:

以上就是PHP 编写基本的 Socket 程序的详细内容,更多请关注 第一PHP社区 其它相关文章!


推荐阅读
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • 禁止程序接收鼠标事件的工具_VNC Viewer for Mac(远程桌面工具)免费版
    VNCViewerforMac是一款运行在Mac平台上的远程桌面工具,vncviewermac版可以帮助您使用Mac的键盘和鼠标来控制远程计算机,操作简 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
author-avatar
书友58612107_778
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有