所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口
以上来自百度(实际则就是一种连接)
当然PHP中还封装了其他两种类型的协议,不常用(SOCK_SEQPACKET 提供一个顺序化的、可靠的、全双工的、面向连接的、固定最大长度的数据通信;数据端通过接收每一个数据段来读取整个数据包和SOCK_RDM 提供一个可靠的数据层,但不保证到达顺序。一般的操作系统都未实现此功能。)
PHP中封装了以socket开头和stream开头的两种函数,都可以实现Unix套接字通信,具体可以查看PHP官方手册
Unix套接字还分无命名的(用于父子、兄弟等有血缘关系进程通信)和命名的(任何进程都可以通信)
无命名Unix套接字通信TCP协议和UDP协议都可以使用
<?php
/**
* Created by PhpStorm
* User: 北溟有鱼QAQ
* Date: 2021-11-06
* Time: 15:35
* Email: 1769360227@qq.com
*/
$fd = [];
//返回两个文件描述符用于读写 $fd[0] 读 $fd[1] 写
socket_create_pair(AF_UNIX,SOCK_STREAM,0,$fd);
$pid = pcntl_fork();
//子进程接收
if($pid ==0)
{
while (1)
{
//接收数据
$data = socket_read($fd[0],128);
if($data)
{
fprintf(STDOUT,"recv--%s\n",$data);
}
//判断接收到的是不是quit
if(strncasecmp($data,'quit',4) == 0)
{
break;
}
}
exit(0);
}
//父进程发送
while (1)
{
$data = fread(STDIN,128);
if($data)
{
//发送数据 MSG_EOR 表示记录标记。发送的数据完成记录。
socket_send($fd[1],$data,strlen($data),MSG_EOR);
}
if(strncasecmp($data,'quit',4) == 0)
{
break;
}
}
//回收子进程
$pid = pcntl_wait($status);
fprintf(STDOUT,"child exit pid=%d\n",$pid);
执行代码,并查看打印结果,可以看到,父进程发送,子进程可以正常接收到数据
<?php
/**
* Created by PhpStorm
* User: 北溟有鱼QAQ
* Date: 2021-12-09
* Time: 17:06
* Email: 1769360227@qq.com
*/
//服务端
$file = 'unix_socket';
//创建socket
$socket = socket_create(AF_UNIX,SOCK_STREAM,0);
//绑定socket到文件
socket_bind($socket,$file);
//监听
socket_listen($socket);
//接收连接 阻塞方式,并且返回socket连接
$recv = socket_accept($socket);
if($recv)
{
while (1)
{
$data = socket_read($recv,128);
if($data)
{
fprintf(STDOUT,"recv form client %s\n",$data);
socket_send($recv,$data,strlen($data),MSG_EOR);
}
if(strncasecmp($data,'quit',4) == 0)
{
exit;
}
}
}
socket_close($socket);
socket_close($recv);
<?php
/**
* Created by PhpStorm
* User: 北溟有鱼QAQ
* Date: 2021-12-09
* Time: 17:34
* Email: 1769360227@qq.com
*/
$file = 'unix_socket';
//创建socket
$socket = socket_create(AF_UNIX,SOCK_STREAM,0);
//连接socket
if(socket_connect($socket,$file))
{
fprintf(STDOUT,"connect ok\n");
while (1)
{
//开两个进程,一个发送,一个接收
$pid = pcntl_fork();
if($pid == 0)
{
$data = socket_read($socket,128);
if($data){
fprintf(STDOUT,'recv form server %s',$data);
}
if(strncasecmp($data,'quit',4) == 0)
{
exit(0);
}
}
$data = fread(STDIN,128);
if($data)
{
socket_send($socket,$data,strlen($data),MSG_EOR);
}
if(strncasecmp($data,'quit',4) == 0)
{
break;
}
}
$pid = pcntl_wait($status);
fprintf(STDOUT,"exit pid %d\n",$pid);
socket_close($socket);
}
执行代码看到以下结果,不同进程之间可以进行通信
并且在执行代码时,使用
strace
命令进行追踪,可以看到,在没有客户端连接时,代码则会在accept进行阻塞,当客户端连接后,代码则会在recvform进行阻塞,等待接收数据
多次启动服务端监听文件时,会报address已被占用的错误,所以需要每次在重启的时候自行处理
本文为北溟有鱼QAQ原创文章,转载无需和我联系,但请注明来自北溟有鱼QAQ https://www.amdzz.cn
最新评论