这篇文章将会介绍一下 Socket 编程中相关的 PHP 函数,并简单实现一个 C/S 的交互
Socket 的官方解释:
在网络编程中最经常使用的方案即是Client/Server(客户机/服务器)模型。在这种方案中客户应用程序向服务器程序请求服务。一个服务程序一般在一个众所周知的地址监听对服务的请求,也就是说,服务进程一 直处于休眠状态,直到一个客户向这个服务的地址提出了链接请求。在这个时刻,服务程序被"惊醒"而且为客户提供服务-对客户的请求做出适当的反应。为了方便这种Client/Server模型的网络编程,90年代初,由Microsoft联合了其余几家公司共同制定了一套WINDOWS下的网络编程接口,即WindowsSockets规范,它不是一种网络协议,而是一套开放的、支持多种协议的Windows下的网络编程接口。如今的Winsock已经基本上实现了与协议无关,你可使用Winsock来调用多种协议的功能,但较常使用的是TCP/IP协议。Socket实际在计算机中提供了一个通讯端口,能够经过这个端口与任何一个具备Socket接口的计算机通讯。应用程序在网络上传输,接收的信息都经过这个Socket接口来实现php
咱们能够简单的把 Socket 理解为一个能够连通网络上不一样计算机应用程序之间的管道,把一堆数据从管道的 A 端扔进去,则会从管道的 B 端(同时还能够从C、D、E、F……端冒出来)。linux
注意
:咱们会在不一样语境下使用不一样的词语去修饰 socket,你只须要对它有个概念就行了,由于 socket 自己就没有真正意义上的实体编程
Socket 通讯依次会进行 Socket 建立、 Socket 绑定、Socket 监听、Socket 收发、Socket 关闭几个阶段,下面咱们列举出 PHP 网络编程中最经常使用也是必不可少的几个经常使用的函数进行进一步的说明。服务器
TODO : 建立一个新的 socket 资源
函数原型: resource socket_create ( int $domain , int $type , int $protocol )
它包含三个参数,分别以下:网络
AF
的释义就 address family
,地址族的意思,咱们经常使用的有 ipv四、ipv6SOCK_STREAM
,基于字节流的SOCKET类型,也是TCP协议使用的类型TODO : 将建立的 socket 资源绑定到具体的 ip 地址和端口
函数原型: bool socket_bind ( resource $socket , string $address [, int $port = 0 ] )
dom
它包含三个参数,分别以下:socket
socket_create
建立的 socket 资源,能够认为是 socket 对应的 idTODO : 在具体的地址下监听 socket 资源的收发操做
函数原型: bool socket_listen ( resource $socket [, int $backlog = 0 ] )
函数
它包含两个个参数,分别以下:spa
socket_create
建立的socket资源TODO : 监听以后,接收一个即未来临的新的链接,若是链接创建成功,将返回一个新的 socket 句柄(你能够理解为子进程,一般父进程用来接收新的链接,子进程负责具体的通讯)
函数原型: resource socket_accept ( resource $socket )
命令行
socket_create
建立的socket资源TODO : 将指定的数据发送到 对应的 socket 管道
函数原型: int socket_write ( resource $socket , string $buffer [, int $length ] )
socket_create
建立的socket资源socket
资源中的数据socket
资源中的buffer
的长度,若是长度大于buffer
的容量,则取buffer
的容量TODO : 获取传送的数据
函数原型: int socket_read ( resource $socket , int $length )
socket_create
建立的socket资源socket
资源中的buffer
的长度TODO : 关闭 socket 资源
函数原型: void socket_close ( resource $socket )
socket_accept
或者socket_create
产生的资源,不能用于stream
资源的关闭因为建立一个SOCKET的流程老是 socket、bind、listen,因此PHP提供了一个很是方便的函数一次性建立、绑定端口、监听端口
函数原型: resource stream_socket_server ( string $local_socket [, int &$errno [, string &$errstr [, int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN [, resource $context ]]]] )
stream_context_create
函数建立的资源流上下文基于上面的函数咱们能够很方便的去构建 socket 通讯程序(在这里我但愿读者能单独创建一个目录好比socket
由于后续咱们还会创建不少文件)咱们先编辑一个服务端程序 server.php
,以下:
<?php date_default_timezone_set("Asia/Shanghai"); error_reporting(E_NOTICE ); /* 确保在链接客户端时不会超时 */ set_time_limit(0); $ip = '127.0.0.1'; $port = 8090; /* +------------------------------- * @socket通讯整个过程 +------------------------------- * @socket_create * @socket_bind * @socket_listen * @socket_accept * @socket_read * @socket_write * @socket_close +-------------------------------- */ /*---------------- 如下操做都是手册上的 -------------------*/ if(($sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) { echo "socket_create() Why failure is:".socket_strerror($sock)."\n"; } if(($ret = socket_bind($sock,$ip,$port)) < 0) { echo "socket_bind() Why failure is:".socket_strerror($ret)."\n"; } if(($ret = socket_listen($sock,4)) < 0) { echo "socket_listen() Why failure is:".socket_strerror($ret)."\n"; } echo "Start time:".date('Y-m-d H:i:s') . PHP_EOL; echo "Listening at ".$ip.':'.$port.PHP_EOL; do { /* 建立新的链接 */ if (($msgsock = socket_accept($sock)) < 0) { echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n"; break; } else { # 链接成功输出 Socket id $i = (int)$msgsock; echo "welcome client $i"; # 向客户端通讯(反馈) $msg ="链接成功!\n"; socket_write($msgsock, $msg, strlen($msg)); } socket_close($msgsock); } while (true); socket_close($sock); ?>
再编辑一个客户端程序client.php
,以下:
<?php set_time_limit(0); $port = 8090; $ip = "127.0.0.1"; /* +------------------------------- * 客户端 socket 链接整个过程 +------------------------------- * @socket_create * @socket_connect * @socket_write * @socket_read * @socket_close +-------------------------------- */ /** * @socket_connect:客户端发起套接字链接 * @param socket resource $socket 建立的$socket资源 * @param address string SOCK_STREAM IP地址|Unix套接字 * @param port int 端口 */ /** * @socket_create:建立并返回一个套接字 * @param domain string AF_INET IPV4 网络协议 * @param type string SOCK_STREAM 全双工字节流(可用的套接字类型) * @param protocol string SOL_TCP 具体协议(IPV4下的TCP协议) * @param return 套接字 */ $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($socket < 0) { echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n"; }else { echo "try to connect '$ip' port: '$port'...\n"; } $result = socket_connect($socket, $ip, $port); #socket_connect的返回值应该是boolean值 if ($result < 0) { echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n"; }else { # 链接成功输出提示信息 echo "connect successfully\n"; # 向服务端发送数据 socket_write($socket, " hello ", 1024); # 获取服务端数据 $result = socket_read($socket, 1024); echo "服务器回传数据为:" . $result; echo "CLOSE SOCKET...\n"; socket_close($socket); echo "CLOSE OK\n"; } ?>
而后咱们打开终端(命令行)进入文件目录下依次执行:
php server.php php client.php
运行效果以下:
注意
服务器监听时进程是挂起的不能进行其余操做,你可能须要另起一个终端执行客户端程序
本篇文章就是为你们整理了一下 PHP Socket 编程经常使用的函数并解释了一下各自的意义,而后写了一个简单的 C/S 交互,但愿你们对网络编程有个比较直观的认识,下篇文章我会简单讲讲进程在网络编程中的做用,这也是为后面网络模型的讲解打个基础