Swoole Process多进程实现TCP服务器

作者: 温新

分类: 【高性能PHP】

阅读: 1546

时间: 2021-04-18 13:30:19

PHP可以使用自带的pcntl实现多进程,这里有个简单的小案例,不妨看看,PHP多进程的使用

下面模拟一个TCP服务器。设置3个子进程,主进程启动之后会启动3个子进程用于处理客户端连接及请求操作。当子进程退出之后,主进程会重新创建子进程,若主进程退出,则子进程在处理完当前请求后退出。

Swoole版本为4.6.4

一、创建多进程TCP服务器

文件:TcpServer.php

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(152, 26, 26)"><?</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">namespace</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">Swoole</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">TcpServer</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 主进程ID</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">private</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$mpid</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 子进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">private</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$pids</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> [];</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 网络套接字</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">private</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$socket</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 创建的最大进程数</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">const</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">MAX_PROCESS</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">3</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">/**</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(170, 85, 0)">* 服务器主进程业务逻辑</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(170, 85, 0)">*/</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">run</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 主进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span>(<span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> () {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">/**</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">*posix_getpid() PHP函数。返回当前进程ID</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">*/</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 将当前进程作为主进程ID</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">mpid</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">posix_getpid</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(51, 0, 170)">time</span>() . <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">主进程ID </span>{<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">mpid</span>}<span style="box-sizing: border-box;color: rgb(170, 17, 17)">\n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">/**</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">*stream_socket_server() PHP函数。创建一个套接字</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">*/</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 创建 TCP 服务器并获取套接字</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">socket</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">stream_socket_server</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"tcp://192.168.172.130:9501"</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$errno</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$errstr</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(152, 26, 26)">!</span><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">socket</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(119, 0, 136)">exit</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"Server start error: </span><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$errstr</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">--- </span><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$errno</span><span style="box-sizing: border-box;color: rgb(170, 17, 17)">"</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 启动子进程处理请求</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">for</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$i</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">0</span>; <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$i</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)"><</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">self</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">MAX_PROCESS</span>; <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$i</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">++</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">startWorkerProcess</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"等待客户端连接...\n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 主进程等待子进程退出,必须是死循环</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">while</span> (<span style="box-sizing: border-box;color: rgb(17, 102, 68)">1</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(119, 0, 136)">foreach</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">pids</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">as</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$k</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=></span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$pid</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$pid</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 回收结束运行的子进程,以避免僵尸进程出现</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$ret</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">wait</span>(<span style="box-sizing: border-box;color: rgb(34, 17, 153)">false</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                        <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$ret</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(51, 0, 170)">time</span>() . <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"工作进程 </span><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$pid</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">退出, 将启动... \n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 子进程退出后重新启动一个新的子进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                            <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">startWorkerProcess</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">unset</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">pids</span>[<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$k</span>]);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                        }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(51, 0, 170)">sleep</span>(<span style="box-sizing: border-box;color: rgb(17, 102, 68)">1</span>); <span style="box-sizing: border-box;color: rgb(170, 85, 0)">//让出 1s 时间给CPU</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        }, <span style="box-sizing: border-box;color: rgb(34, 17, 153)">false</span>, <span style="box-sizing: border-box;color: rgb(34, 17, 153)">false</span>); <span style="box-sizing: border-box;color: rgb(170, 85, 0)">//不启用管道通信</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 让当前进程变成一个守护进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">daemon</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 执行 fork 系统调用,启动进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 注意:start 之后的变量子进程里面是获取不到的</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">start</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 创建子进程,接收客户端连接并处理</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">private</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">startWorkerProcess</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 子进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span>(<span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> (<span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 子进程业务逻辑</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">acceptClient</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        }, <span style="box-sizing: border-box;color: rgb(34, 17, 153)">false</span>, <span style="box-sizing: border-box;color: rgb(34, 17, 153)">false</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 启动子进程并获取子进程 ID</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$pid</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$process</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">start</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">pids</span>[] <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$pid</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 等待客户端连接并处理</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">private</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">acceptClient</span>(<span style="box-sizing: border-box;color: rgb(152, 26, 26)">&</span><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">//子进程一直等待客户端连接,不能退出</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(119, 0, 136)">while</span> (<span style="box-sizing: border-box;color: rgb(17, 102, 68)">1</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 从主进程创建的网络套接字上获取连接</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">stream_socket_accept</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">socket</span>, <span style="box-sizing: border-box;color: rgb(152, 26, 26)">-</span><span style="box-sizing: border-box;color: rgb(17, 102, 68)">1</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 如果定义了连接建立回调函数,则在连接上执行该回调</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">onConnect</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(0, 0, 0)">call_user_func</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">onConnect</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 开始循环读取客户端请求消息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$recv</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">''</span>; <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 实际收到的消息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$buffer</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">''</span>; <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 缓冲消息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">while</span> (<span style="box-sizing: border-box;color: rgb(17, 102, 68)">1</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 检查主进程是否正常,不正常则退出子进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">checkMpid</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 读取客户端请求消息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$buffer</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(51, 0, 170)">fread</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>, <span style="box-sizing: border-box;color: rgb(17, 102, 68)">20</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 没有收到正常消息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$buffer</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">===</span> <span style="box-sizing: border-box;color: rgb(34, 17, 153)">false</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">||</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$buffer</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">===</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">''</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 如果服务器设置了连接关闭回调函数,则在当前连接上执行该回调</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">onClose</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                        <span style="box-sizing: border-box;color: rgb(0, 0, 0)">call_user_func</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">onClose</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 结束读取消息,退出当前循环,等待下一个客户端连接</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">break</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 消息结束符的位置</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$pos</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(51, 0, 170)">strpos</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$buffer</span>, <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"\n"</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$pos</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">===</span> <span style="box-sizing: border-box;color: rgb(34, 17, 153)">false</span>) {  <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 没有读取完,继续读取</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$recv</span> .<span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$buffer</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                } <span style="box-sizing: border-box;color: rgb(119, 0, 136)">else</span> {  <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 读取完毕,开始处理请求消息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 处理收到的消息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$recv</span> .<span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(51, 0, 170)">trim</span>(<span style="box-sizing: border-box;color: rgb(51, 0, 170)">substr</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$buffer</span>, <span style="box-sizing: border-box;color: rgb(17, 102, 68)">0</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$pos</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">+</span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">1</span>));</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 如果服务器定义了消息处理回调函数,则在当前连接上将消息传入回调函数并执行该回调</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">onMessage</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                        <span style="box-sizing: border-box;color: rgb(0, 0, 0)">call_user_func</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">onMessage</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$recv</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 如果接收到 quit 消息,表示关闭此连接,等待下一个客户端连接</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$recv</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">==</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"quit"</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                        <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"Client close connection\n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                        <span style="box-sizing: border-box;color: rgb(51, 0, 170)">fclose</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                        <span style="box-sizing: border-box;color: rgb(119, 0, 136)">break</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                    <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$recv</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">''</span>; <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 清空消息,准备下一次接收</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">                }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">/**</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(170, 85, 0)">* 如果主进程已退出,则子进程也退出,避免孤儿进程出现</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(170, 85, 0)">* @param Process $worker</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">     <span style="box-sizing: border-box;color: rgb(170, 85, 0)">*/</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">checkMpid</span>(<span style="box-sizing: border-box;color: rgb(152, 26, 26)">&</span><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 检测主进程是否存在,如果不存在,则退出子进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(152, 26, 26)">!</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">Process</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">kill</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$this</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">mpid</span>, <span style="box-sizing: border-box;color: rgb(17, 102, 68)">0</span>)) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(119, 0, 136)">exit</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 这句提示,实际是看不到的,需要写到日志中</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"Master process exited, I [</span>{<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$worker</span>[<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'pid'</span>]}<span style="box-sizing: border-box;color: rgb(170, 17, 17)">] also quit\n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$server</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">TcpServer</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 定义连接建立回调函数</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$server</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">onConnect</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"onConnect -- accepted "</span> . <span style="box-sizing: border-box;color: rgb(0, 0, 0)">stream_socket_get_name</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>, <span style="box-sizing: border-box;color: rgb(34, 17, 153)">true</span>) . <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"\n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">};</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 定义收到消息回调函数</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$server</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">onMessage</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$msg</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"onMessage --"</span> . <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$msg</span> . <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"\n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(51, 0, 170)">fwrite</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>, <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"received "</span> . <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$msg</span> . <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"\n"</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">};</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 定义连接关闭回调函数</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$server</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">onClose</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"onClose --"</span> . <span style="box-sizing: border-box;color: rgb(0, 0, 0)">stream_socket_get_name</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$conn</span>, <span style="box-sizing: border-box;color: rgb(34, 17, 153)">true</span>) . <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"\n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">};</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 启动服务器主进程</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 85, 170)">$server</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">run</span>();</span>

二、创建协程客户端

关于一些资料,写的时候可能比较早,而swoole是发展的,方法可能会做调整,但也适用。尽管可以适用,但是最好还是与文档保持一致。关于swoole学习多翻阅文档是个好习惯。

文件:TcpClient.php

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(152, 26, 26)"><?</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Swoole\Coroutine\Client</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">Swoole\Coroutine\run</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">run</span>(<span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span>(){</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$client</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">new</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Client</span>(<span style="box-sizing: border-box;color: rgb(0, 0, 0)">SWOOLE_SOCK_TCP</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 连接指定的TCP服务器</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$client</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">connect</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'192.168.172.130'</span>,<span style="box-sizing: border-box;color: rgb(17, 102, 68)">9501</span>,<span style="box-sizing: border-box;color: rgb(17, 102, 68)">0.5</span>)) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(170, 17, 17)">"connect failed. Error: </span>{<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$client</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">errCode</span>}<span style="box-sizing: border-box;color: rgb(170, 17, 17)">\n"</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 建立连接成功后发送消息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$client</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">send</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">"hello world\n"</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 打印接收到的消息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">echo</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$client</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">recv</span>() . <span style="box-sizing: border-box;color: rgb(0, 0, 0)">PHP_EOL</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(51, 0, 170)">sleep</span>(<span style="box-sizing: border-box;color: rgb(17, 102, 68)">3</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 关闭连接</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$client</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">close</span>();</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">});</span>

三、启动TCP服务器

启动TCP服务器

php TcpServer.php

查看TCP服务器

<span style="box-sizing: border-box;padding-right: 0.1px">ps aux | grep php</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">root        938  0.0  1.2 129164 12412 ?        Ss   19:26   0:00 php-fpm: master process (/usr/local/php-8.0.1/etc/php-fpm.conf)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">www         951  0.0  0.6 129164  6636 ?        S    19:26   0:00 php-fpm: pool www</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">www         952  0.0  0.6 129164  6640 ?        S    19:26   0:00 php-fpm: pool www</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">root       2969  0.0  0.7 129044  7112 ?        S    20:46   0:00 php TcpServer.php</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">root       2970  0.0  0.6 131096  6468 ?        S    20:46   0:00 php TcpServer.php</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">root       2971  0.0  0.6 131096  6468 ?        S    20:46   0:00 php TcpServer.php</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">root       2972  0.0  0.6 131096  6960 ?        S    20:46   0:00 php TcpServer.php</span>

可以看到,主进程ID为2969,主进程启动后创建了3个子进程。

四、客户端连接

客户端界面

开启两个窗口进行连接TCP服务器。

窗口一:

<span style="box-sizing: border-box;padding-right: 0.1px">php TcpClient.php </span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">connect failed. Error: 0</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">received hello world</span>

窗口二:

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">TcpClient</span>.<span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span> </span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">connect</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">failed</span>. <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Error</span>: <span style="box-sizing: border-box;color: rgb(17, 102, 68)">0</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">received</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">hello</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">world</span></span>

服务器界面窗口

<span style="box-sizing: border-box;padding-right: 0.1px"> 1618749993 Master process, pid 2969</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">Waiting client start...</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">onConnect -- accepted 192.168.172.130:50060</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">onMessage --hello world</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">onClose --192.168.172.130:50060</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">onConnect -- accepted 192.168.172.130:50062</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">onMessage --hello world</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">onClose --192.168.172.130:50062</span>

此文学习自 学院君;客户端代码来自于Swoole官方文档。

请登录后再评论