PHP开源Hub
致力于开发者的提升

玩转 PHP 网络编程首篇

先扯蛋

本来有点想删掉了【一直在草稿里呆好久了,想想还是发布吧,兴许可能有人用得上】
laravel里的系列文章功能用得不顺手,不知道咋搞的,我就直接粗暴的粘链接了。时间原因,本来是想再深入的,想想有机会再补充吧。

PHP socket 手册

手册地址

使用需求

系统平台
玩转PHP网络编程全套

php -m 或 php --ri sockets

玩转PHP网络编程全套

显示如上,表示php已经支持socket扩展

几行代码先运行

$ip = "0.0.0.0";
$port = $argv[1];
$sockefd = socket_create(AF_INET,SOCK_STREAM,0);
echo $sockefd.PHP_EOL;
$pid = posix_getpid();
echo "pid=".$pid.PHP_EOL;
echo `ls -al /proc/{$pid}/fd`;//为了方便看该进程生成的数据
socket_bind($sockefd,$ip,$port);
socket_listen($sockefd,5);

while (1){}

然后我php socket1.php 12345
结果显示如下
玩转PHP网络编程全套
我先来解释先
Resource id #4那是PHP返回的,在PHP里称为资源
0它是一个字符输入设备也是文件描述符【linux皆文件】
1它是一个字符输出设备也是文件描述符
2同样的也是
3比较特殊它是一个epoll类型的文件,链接着一个匿名节点
4是一个socket类型的文件,它的结点是9460457
5是一个管道文件
实际上我去对应的目录看是没有这文件的,可以先不理它
在linux上它是这样的
玩转PHP网络编程全套
接下来我们继续看socket:[9460457]->4
先看它的网络状态,我们cat net/tcp即可
玩转PHP网络编程全套
先对几个重要的选项解释一下
local_address表示本地ip和端口号用16进制表示
rem_address 远程服务器ip和端口
st 表示套接字状态
1 TCP_ESTABLISHED
2 TCP_SYN_SENT
3 TCP_SYN_RECV
4 TCP_FIN_WAIT1
5 TCP_FIN_WAIT2
6 TCP_TIME_WAIT
7 TCP_CLOSE
8 TCP_CLOSE_WAIT
9 TCP_LAST_ACK
10 TCP_LISTEN 16进制就是A
11 TCP_CLOSING
tx_queue 发送队列中的数据长度
rx_queue 接收的数据长度
tr 定时器类型
0未启动定时
1开启socket 定时重传机制
4开启持续定时
2开启连接定时器 FIN_WAIT2定时
3 TIME_WAIT定时

tm->when 超时时间
retrnsmt 超时重传次数
uid 用户的id
inode socket套接字对应的结点inode
大家都了解TCP数据流拥有自己的接收缓冲区和发送缓冲区,同时呢具有超时重传机制和数据应答确诊机制

这个socket它的状态用netstat -antp查看就是这样的
玩转PHP网络编程全套

所以我们socket_create后它创建了一个TCP并且处于监听状态中即LISTEN。

我们在代码的最后一句加上了while就是让它一直循环在那运行R(running),我们在该进程生成的目录下可以查看
玩转PHP网络编程全套

发起一个网络连接一下看看效果

在发起连接之前我们先要执行tcpdump -i lo port 12345
然后使用telnet工具去连接,得到的结果如下
玩转 PHP 网络编程全套
22:33:44.827309 IP localhost.37510 > localhost.italk: Flags [S], seq 1537400892
01:50:55.605018 IP localhost.italk > localhost.37510: Flags [S.], seq 1228325870, ack 1537400893
22:33:44.827328 IP localhost.37510 > localhost.italk: Flags [.], ack 1

前面的是时间,localhost.37510是客户端的ip和系统分配的随机端口
而localhost.italk是本机
Flags

  • SYN 表示发起一个连接
  • ACK 一个应答
  • RST 重新发起连接
  • PSH 在传输数据时会有这个标志位
  • URG 紧急标志位
  • FIN 一个关闭报文

seq 表示源IP向目标IP传输的序列号
对端应答的时候必须在其基础上加1操作
ack 表示确认序列号,一般在seq上加1进行应答确认
以上的内容完成了大家比较熟悉的TCP连接三次握手

我想知道细节,想知道它到底在干嘛

下面我来添加几句代码,我们来更清楚的知道它们是怎么玩在一起的,是怎么进行通信的

....
while (1){

    $connfd = socket_accept($sockefd);
    echo $connfd.PHP_EOL;
    socket_write($connfd,"hello,php 是世界上是好的语言");

}

然后输入如下命令

strace -f php socket1.php 12345

抽核心大概流程

  • exec
    玩转 PHP 网络编程全套
  • read socket1.php
    玩转 PHP 网络编程全套
  • create socket
    玩转 PHP 网络编程全套
  • exec sh
    玩转 PHP 网络编程全套
  • bind,listen,accept
    玩转 PHP 网络编程全套
    就大概这么几句,创建socket返回文件描述符4,然后bind绑定,监听,最后呢在accept函数阻塞进程【Sleeping状态】cpu已经做其它事情了,毕竟它在”睡觉中”
    玩转 PHP 网络编程全套
    玩转 PHP 网络编程全套

接下来我们同样用telnet工具来连接并传输数据
玩转 PHP 网络编程全套
玩转 PHP 网络编程全套
玩转 PHP 网络编程全套

玩转 PHP 网络编程全套

接下来我们再加几句代码让其它成基本的响应给客户端

while (1){
    $connfd = socket_accept($sockefd);
    echo $connfd.PHP_EOL;
    socket_write($connfd,"hello,php 是世界上是好的语言");
    echo socket_read($connfd,4098,PHP_BINARY_READ);
}

玩转 PHP 网络编程全套

我们看到php语言低层调用了c函数【任何语言都是一样】
都是先创建一个socketfd,再把端口和地址绑架到它身上,再listen进行监听,直到accept阻塞,有客户端连接时才会唤醒该进程来处理数据。所以务必动手实验才能领略阻塞和唤醒的感觉。

玩转 PHP 网络编程全套

赞(0) 打赏
未经允许不得转载PHP开源Hub » 玩转 PHP 网络编程首篇

评论 1

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #1

    ggg

    Endeavor4个月前 (05-24)回复

PHP开源Hub-致力于互联网开发者的成长

技术群聊软文发表

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏