宁泽林_NiZerin - 互联网技术博客

  • PHP
  • Go
  • Java
  • Rust
  • Python
  • 交流群
  • 关于我
  • 留言版
  1. 首页
  2. PHP
  3. 正文

玩转 PHP 网络编程首篇

2020年5月15日 2235点热度 0人点赞 1条评论

先扯蛋

本来有点想删掉了【一直在草稿里呆好久了,想想还是发布吧,兴许可能有人用得上】
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 网络编程全套

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: php
最后更新:2020年5月15日

NiZerin

博主已经躺平了,后面很少会更新博客。

打赏 点赞
< 上一篇
下一篇 >

文章评论

  • Endeavor

    ggg

    2020年5月24日
    回复
  • razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
    取消回复

    分类
    • Angular
    • CSS3
    • docker
    • Flutter
    • git
    • Go
    • H5
    • Java
    • JavaScript
    • Laravel
    • linux
    • Node.js
    • PHP
    • Python
    • React
    • redis
    • Vue.js
    • windows
    • WordPress
    • 交流
    • 小程序
    • 工具
    • 网站公告
    标签聚合
    javascript translations laravel go flutter vue wordpress php
    友情链接
    • PHP函数字典
    • 宝塔运维特惠
    • 科学上网
    • 阿里云特惠

    COPYRIGHT © 2021 nizer.in. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang