<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Socket on 勇气</title><link>https://courages.us/tag/socket/</link><description>Recent content in Socket on 勇气</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Fri, 20 Nov 2020 11:32:28 +0800</lastBuildDate><atom:link href="https://courages.us/tag/socket/index.xml" rel="self" type="application/rss+xml"/><item><title>即时通信IRC服务Oragono</title><link>https://courages.us/%E5%8D%B3%E6%97%B6%E9%80%9A%E4%BF%A1irc%E6%9C%8D%E5%8A%A1oragono/</link><pubDate>Wed, 18 Nov 2020 15:19:05 +0800</pubDate><guid>https://courages.us/%E5%8D%B3%E6%97%B6%E9%80%9A%E4%BF%A1irc%E6%9C%8D%E5%8A%A1oragono/</guid><description>&lt;p&gt;前一篇讲了&lt;a class="link" href="https://courages.us/%e5%8d%b3%e6%97%b6%e9%80%9a%e4%bf%a1xmpp%e6%9c%8d%e5%8a%a1%e5%99%a8ejabberd-openfire/" target="_blank" rel="noopener"&#10; &gt;XMPP通信&lt;/a&gt;，还有一种比它还早的协议&lt;a class="link" href="https://zh.wikipedia.org/wiki/IRC" target="_blank" rel="noopener"&#10; &gt;IRC（Internet Relay Chat）&lt;/a&gt;，是一种简单的文本聊天协议，支持一对一聊天和群聊（频道）。通常IRC聊天只需要昵称而不需要密码（也可以使用密码），这与XMML不同，使得它可以作为公开的聊天频道，比如游戏直播平台Twitch就使用类似的功能来实现聊天。IRC同样有许多服务端，比如&lt;a class="link" href="https://www.inspircd.org/" target="_blank" rel="noopener"&#10; &gt;InspIRCd&lt;/a&gt;和客户端软件，比如&lt;a class="link" href="https://irssi.org/" target="_blank" rel="noopener"&#10; &gt;Irssi&lt;/a&gt;，也可以直接连接公开的IRC服务器，比如&lt;a class="link" href="https://freenode.net/" target="_blank" rel="noopener"&#10; &gt;Freenode&lt;/a&gt;。事实上IRC协议非常简单，只要能对相应的&lt;a class="link" href="https://ircv3.net/irc/" target="_blank" rel="noopener"&#10; &gt;命令&lt;/a&gt;作出响应就可以在各个客户端之间通信，因此有许多不同编程语言的服务端/客户端实现。&lt;a class="link" href="https://github.com/oragono/oragono" target="_blank" rel="noopener"&#10; &gt;Oragono&lt;/a&gt;便是IRC 服务器的Golang实现，支持&lt;a class="link" href="https://ircv3.net/" target="_blank" rel="noopener"&#10; &gt;IRCv3&lt;/a&gt;，支持SASL/LDAP认证，支持服务端保存消息历史记录。&lt;br&gt;&#10;Oragono运行很简单，克隆代码，编辑配置文件就可以了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHANGELOG.md     README           default.yaml     docs             languages        oragono          oragono.motd     traditional.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 cp default.yaml ircd.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ./oragono mkcerts&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020/11/11 12:01:04 making self-signed certificates&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020/11/11 12:01:04  making cert &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; :6697 listener&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020/11/11 12:01:04   Certificate created at fullchain.pem : privkey.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHANGELOG.md     README           default.yaml     docs             fullchain.pem    ircd.yaml        languages        oragono          oragono.motd     privkey.pem      traditional.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜  oragono24 ./oragono run&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.320Z : info : server : oragono-2.4.0 starting&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.320Z : info : server : Using config file : ircd.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.320Z : info : server : Using datastore : ircd.db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.344Z : info : server : Proxied IPs will be accepted from : localhost&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on &lt;span style="color:#f92672"&gt;[&lt;/span&gt;::1&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:6667, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on :6697, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on :8097, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : listeners : now listening on 127.0.0.1:6667, tls&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tlsproxy&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, tor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false, websocket&lt;span style="color:#f92672"&gt;=&lt;/span&gt;false.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:29.345Z : info : server : Server running&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:38.386Z : info : connect-ip : Client connecting: real IP 192.168.33.1, proxied IP &amp;lt;nil&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:38.439Z : info : accounts : client : * : logged into account : kiwi-n30&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:38.442Z : info : connect : Client connected &lt;span style="color:#f92672"&gt;[&lt;/span&gt;kiwi-n30&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;u:~u&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;r:https://kiwiirc.com/&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:40.955Z : info : connect-ip : Client connecting: real IP 192.168.33.1, proxied IP &amp;lt;nil&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:40.963Z : info : connect : Client connected &lt;span style="color:#f92672"&gt;[&lt;/span&gt;kiwi-n28&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;u:~u&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;r:https://kiwiirc.com/&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:56.198Z : info : connect-ip : Client connecting: real IP 192.168.33.1, proxied IP &amp;lt;nil&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2020-11-13T03:09:56.209Z : info : connect : Client connected &lt;span style="color:#f92672"&gt;[&lt;/span&gt;kiwi-n29&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;u:~u&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;r:https://kiwiirc.com/&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;编辑ircd.yml，设置管理密码，启用一下WebSocket，保存历史消息到MySQL。opers/admin管理密码在认证管理员的时候使用的，可以使用命令oragono genpasswd生成。ircd.db用来保存注册用户，使用的并不是SQLite，而是Golang实现的一个嵌入式的内存Key/Value存储&lt;a class="link" href="https://github.com/tidwall/buntdb" target="_blank" rel="noopener"&#10; &gt;BuntDB&lt;/a&gt;，可以持久化到硬盘。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# network configuration&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;network&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# name of the network&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;OragonoTest&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# server configuration&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;server&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# server name&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;oragono.test&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# addresses to listen on&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;listeners&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# The standard plaintext port for IRC is 6667. Allowing plaintext over the&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# public Internet poses serious security and privacy issues. Accordingly,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# we recommend using plaintext only on local (loopback) interfaces:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;127.0.0.1:6667&amp;#34;: &lt;/span&gt;&lt;span style="color:#75715e"&gt;# (loopback ipv4, localhost-only)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;[::1]:6667&amp;#34;: &lt;/span&gt; &lt;span style="color:#75715e"&gt;# (loopback ipv6, localhost-only)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# If you need to serve plaintext on public interfaces, comment out the above&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# two lines and uncomment the line below (which listens on all interfaces):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;:6667&amp;#34;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Alternately, if you have a TLS certificate issued by a recognized CA,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# you can configure port 6667 as an STS-only listener that only serves&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;redirects&amp;#34; to the TLS port, but doesn&amp;#39;t allow chat. See the manual&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# for details.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# The standard SSL/TLS port for IRC is 6697. This will listen on all interfaces:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;:6697&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tls&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cert&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fullchain.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;key&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;privkey.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#39;proxy&amp;#39; should typically be false. It&amp;#39;s only for Kubernetes-style load&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# balancing that does not terminate TLS, but sends an initial PROXY line&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# in plaintext.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;proxy&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Example of a Unix domain socket for proxying:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;/tmp/oragono_sock&amp;#34;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Example of a Tor listener: any connection that comes in on this listener will&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# be considered a Tor connection. It is strongly recommended that this listener&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# *not* be on a public interface --- it should be on 127.0.0.0/8 or unix domain:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#34;/hidden_service_sockets/oragono_tor_sock&amp;#34;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# tor: true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# Example of a WebSocket listener:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;:8097&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;websocket&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;tls&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cert&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;fullchain.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;key&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;privkey.pem&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ircd operators&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;opers&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# operator named &amp;#39;admin&amp;#39;; log in with /OPER admin [password]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;admin&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# which capabilities this oper has access to&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;class&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;server-admin&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# custom whois line&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;whois-line&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;is a server admin&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# custom hostname&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;vhost&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;staff&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# normally, operator status is visible to unprivileged users in WHO and WHOIS&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# responses. this can be disabled with &amp;#39;hidden&amp;#39;. (&amp;#39;hidden&amp;#39; also causes the&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# &amp;#39;vhost&amp;#39; line above to be ignored.)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hidden&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# modes are modes to auto-set upon opering-up. uncomment this to automatically&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# enable snomasks (&amp;#34;server notification masks&amp;#34; that alert you to server events;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# see `/quote help snomasks` while opered-up for more information):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#modes: +is acjknoqtuxv&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# operators can be authenticated either by password (with the /OPER command),&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# or by certificate fingerprint, or both. if a password hash is set, then a&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# password is required to oper up (e.g., /OPER dan mypassword). to generate&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# the hash, use `oragono genpasswd`.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;$2a$04$I2Yhr7UF4p3iyEZcKTPJgukLA9mm00B1wQgicJvGZP/gf0u0tbQQy&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# datastore configuration&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;datastore&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# path to the datastore&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;path&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ircd.db&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# if the database schema requires an upgrade, `autoupgrade` will attempt to&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# perform it automatically on startup. the database will be backed&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# up, and if the upgrade fails, the original database will be restored.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;autoupgrade&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# connection information for MySQL (currently only used for persistent history):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;mysql&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;host&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3306&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# if socket-path is set, it will be used instead of host:port&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;#socket-path: &amp;#34;/var/run/mysqld/mysqld.sock&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;user&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;password&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;history-database&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;oragono_history&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;timeout&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;30s&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;IRC服务端设置好了，使用客户端连上去就可以聊天了。IRC协议类似HTTP协议，服务器地址类似irc://irc.freenode.net，但是也可以使用web来连接，前面配置了监听来自8097端口的websocket请求。这里使用web的IRC客户端&lt;a class="link" href="https://kiwiirc.com/" target="_blank" rel="noopener"&#10; &gt;Kiwi IRC&lt;/a&gt;，这是Vue实现的一个web客户端，各个组件之间通过触发/订阅Vue实例状态/事件变化进行通信，支持自定义组件/中间件，这也是Freenode使用的客户端。Kiwiirc主要聚焦连接和消息的处理，比如websocket连接/发送/监听，消息的格式化/通知/声音/状态。它能够连接websocket的IRC服务器，甚至还提供在线&lt;a class="link" href="https://kiwiirc.com/clientbuilder/#/" target="_blank" rel="noopener"&#10; &gt;生成器&lt;/a&gt;，只需要添加websocket url就好了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;windowTitle&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Kiwi IRC with Oragono Test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;startupScreen&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;welcome&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;kiwiServer&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;http://oragono.test&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;restricted&amp;#34;&lt;/span&gt;: false,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;theme&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Default&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;themes&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Default&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/default&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Dark&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/dark&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Coffee&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/coffee&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;GrayFox&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/grayfox&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Nightswatch&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/nightswatch&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Osprey&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/osprey&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Radioactive&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/radioactive&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Sky&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/sky&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Elite&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/themes/elite&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;startupOptions&amp;#34;&lt;/span&gt; : &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;websocket&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;wss://127.0.0.1:8097&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;channel&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;#kiwiirc-default&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;nick&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;kiwi-n?&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;embedly&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;plugins&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;customise&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;static/plugins/customise.html&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行登录后的效果&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_action.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="310px" data-flex-grow="129" height="232" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_action-300x232.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_auth.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="566px" data-flex-grow="236" height="127" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_auth-300x127.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_auth_no.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="660px" data-flex-grow="275" height="109" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_auth_no-300x109.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_channel.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="960px" data-flex-grow="400" height="75" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_channel-300x75.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_channel_register.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="406px" data-flex-grow="169" height="177" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_channel_register-300x177.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_invite.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="293px" data-flex-grow="122" height="245" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_invite-300x245.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_join_history.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="431px" data-flex-grow="179" height="167" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_join_history-300x167.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_join_self.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="452px" data-flex-grow="188" height="159" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_join_self-300x159.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_login.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="566px" data-flex-grow="236" height="127" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_login-300x127.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_oper.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="231px" data-flex-grow="96" height="300" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_oper-289x300.png" width="289"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/kiwi_preload.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="489px" data-flex-grow="204" height="147" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/kiwi_preload-300x147.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;其实IRC是基于TCP连接的文本交互的，也可以使用telnet来模拟&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜ ~ telnet 127.0.0.1 &lt;span style="color:#ae81ff"&gt;6667&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Trying 127.0.0.1...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connected to localhost.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Escape character is &lt;span style="color:#e6db74"&gt;&amp;#39;^]&amp;#39;&lt;/span&gt;.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CAP LS &lt;span style="color:#ae81ff"&gt;302&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:oragono.test CAP * LS * :account-notify account-tag away-notify batch cap-notify chghost draft/channel-rename draft/chathistory draft/event-playback draft/languages&lt;span style="color:#f92672"&gt;=&lt;/span&gt;16,en,~bs,~de,~el,~en-AU,~es,~fi,~fr-FR,~it,~nl,~no,~pl,~pt-BR,~ro,~tr-TR,~zh-CN draft/multiline&lt;span style="color:#f92672"&gt;=&lt;/span&gt;max-bytes&lt;span style="color:#f92672"&gt;=&lt;/span&gt;4096,max-lines&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; draft/register&lt;span style="color:#f92672"&gt;=&lt;/span&gt;before-connect draft/relaymsg&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/ draft/resume-0.5 echo-message extended-join invite-notify labeled-response message-tags multi-prefix oragono.io/nope sasl&lt;span style="color:#f92672"&gt;=&lt;/span&gt;PLAIN,EXTERNAL server-time setname&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:oragono.test CAP * LS :userhost-in-names znc.in/playback znc.in/self-message&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NICK kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;USER kiwi-n26 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; * https://kiwiirc.com/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CAP REQ :account-notify account-tag away-notify batch cap-notify draft/chathistory extended-join invite-notify message-tags multi-prefix server-time userhost-in-names znc.in/self-message&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:02.201Z :oragono.test CAP * ACK :account-notify account-tag away-notify batch cap-notify draft/chathistory extended-join invite-notify message-tags multi-prefix server-time userhost-in-names znc.in/self-message&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CAP END&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;001&lt;/span&gt; kiwi-n26 :Welcome to the Internet Relay Network kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;002&lt;/span&gt; kiwi-n26 :Your host is oragono.test, running version oragono-2.4.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;003&lt;/span&gt; kiwi-n26 :This server was created Fri, &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; Nov &lt;span style="color:#ae81ff"&gt;2020&lt;/span&gt; 00:35:48 UTC&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;004&lt;/span&gt; kiwi-n26 oragono.test oragono-2.4.0 BERTZios CEIMRUabehiklmnoqstuv Iabehkloqv&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;005&lt;/span&gt; kiwi-n26 AWAYLEN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;390&lt;/span&gt; BOT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;B CASEMAPPING&lt;span style="color:#f92672"&gt;=&lt;/span&gt;ascii CHANLIMIT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#75715e"&gt;#:100 CHANMODES=Ibe,k,l,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 MAXLIST=beI:60 :are supported by this server&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;005&lt;/span&gt; kiwi-n26 MAXTARGETS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; MODES MONITOR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; NETWORK&lt;span style="color:#f92672"&gt;=&lt;/span&gt;OragonoTest NICKLEN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;32&lt;/span&gt; PREFIX&lt;span style="color:#f92672"&gt;=(&lt;/span&gt;qaohv&lt;span style="color:#f92672"&gt;)&lt;/span&gt;~&amp;amp;@%+ STATUSMSG&lt;span style="color:#f92672"&gt;=&lt;/span&gt;~&amp;amp;@%+ TARGMAX&lt;span style="color:#f92672"&gt;=&lt;/span&gt;NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;390&lt;/span&gt; UTF8MAPPING&lt;span style="color:#f92672"&gt;=&lt;/span&gt;rfc8265 WHOX draft/CHATHISTORY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; :are supported by this server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;251&lt;/span&gt; kiwi-n26 :There are &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; users and &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; invisible on &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; server&lt;span style="color:#f92672"&gt;(&lt;/span&gt;s&lt;span style="color:#f92672"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;252&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :IRC Operators online&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;253&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; :unregistered connections&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;254&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; :channels formed&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;255&lt;/span&gt; kiwi-n26 :I have &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; clients and &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; servers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;265&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; :Current local users 4, max &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;266&lt;/span&gt; kiwi-n26 &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; :Current global users 4, max &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;375&lt;/span&gt; kiwi-n26 :- oragono.test Message of the day -&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▄▄▄ ▄▄▄· ▄▄ • ▐ ▄&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▪ ▀▄ █·▐█ ▀█ ▐█ ▀ ▪▪ •█▌▐█▪&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▄█▀▄ ▐▀▀▄ ▄█▀▀█ ▄█ ▀█▄ ▄█▀▄▪▐█▐▐▌ ▄█▀▄&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▐█▌.▐▌▐█•█▌▐█ ▪▐▌▐█▄▪▐█▐█▌ ▐▌██▐█▌▐█▌.▐▌&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- ▀█▄▀▪.▀ ▀ ▀ ▀ ·▀▀▀▀ ▀█▄▀ ▀▀ █▪ ▀█▄▀▪&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- This is the default Oragono MOTD.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- If motd-formatting is enabled in the config file, you can use the dollarsign character to&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- create special formatting such as bold, italics and color codes.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- For example, here are a few formatted lines &lt;span style="color:#f92672"&gt;(&lt;/span&gt;enable motd-formatting to see these in action&lt;span style="color:#f92672"&gt;)&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is bold text.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is italics text.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is 4red and 2blue text.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is 4,12red text with a light blue background.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- - this is a normal escaped dollarsign: $&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- And now a few fun colour charts!&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 1,0 &lt;span style="color:#ae81ff"&gt;00&lt;/span&gt; 0,1 &lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; 0,2 &lt;span style="color:#ae81ff"&gt;02&lt;/span&gt; 0,3 &lt;span style="color:#ae81ff"&gt;03&lt;/span&gt; 1,4 &lt;span style="color:#ae81ff"&gt;04&lt;/span&gt; 0,5 &lt;span style="color:#ae81ff"&gt;05&lt;/span&gt; 0,6 &lt;span style="color:#ae81ff"&gt;06&lt;/span&gt; 1,7 &lt;span style="color:#ae81ff"&gt;07&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 1,8 &lt;span style="color:#ae81ff"&gt;08&lt;/span&gt; 1,9 &lt;span style="color:#ae81ff"&gt;09&lt;/span&gt; 0,10 &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt; 1,11 &lt;span style="color:#ae81ff"&gt;11&lt;/span&gt; 0,12 &lt;span style="color:#ae81ff"&gt;12&lt;/span&gt; 1,13 &lt;span style="color:#ae81ff"&gt;13&lt;/span&gt; 1,14 &lt;span style="color:#ae81ff"&gt;14&lt;/span&gt; 1,15 &lt;span style="color:#ae81ff"&gt;15&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,16 &lt;span style="color:#ae81ff"&gt;16&lt;/span&gt; 0,17 &lt;span style="color:#ae81ff"&gt;17&lt;/span&gt; 0,18 &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt; 0,19 &lt;span style="color:#ae81ff"&gt;19&lt;/span&gt; 0,20 &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt; 0,21 &lt;span style="color:#ae81ff"&gt;21&lt;/span&gt; 0,22 &lt;span style="color:#ae81ff"&gt;22&lt;/span&gt; 0,23 &lt;span style="color:#ae81ff"&gt;23&lt;/span&gt; 0,24 &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt; 0,25 &lt;span style="color:#ae81ff"&gt;25&lt;/span&gt; 0,26 &lt;span style="color:#ae81ff"&gt;26&lt;/span&gt; 0,27 &lt;span style="color:#ae81ff"&gt;27&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,28 &lt;span style="color:#ae81ff"&gt;28&lt;/span&gt; 0,29 &lt;span style="color:#ae81ff"&gt;29&lt;/span&gt; 0,30 &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; 0,31 &lt;span style="color:#ae81ff"&gt;31&lt;/span&gt; 0,32 &lt;span style="color:#ae81ff"&gt;32&lt;/span&gt; 0,33 &lt;span style="color:#ae81ff"&gt;33&lt;/span&gt; 0,34 &lt;span style="color:#ae81ff"&gt;34&lt;/span&gt; 0,35 &lt;span style="color:#ae81ff"&gt;35&lt;/span&gt; 0,36 &lt;span style="color:#ae81ff"&gt;36&lt;/span&gt; 0,37 &lt;span style="color:#ae81ff"&gt;37&lt;/span&gt; 0,38 &lt;span style="color:#ae81ff"&gt;38&lt;/span&gt; 0,39 &lt;span style="color:#ae81ff"&gt;39&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,40 &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt; 0,41 &lt;span style="color:#ae81ff"&gt;41&lt;/span&gt; 0,42 &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt; 0,43 &lt;span style="color:#ae81ff"&gt;43&lt;/span&gt; 0,44 &lt;span style="color:#ae81ff"&gt;44&lt;/span&gt; 0,45 &lt;span style="color:#ae81ff"&gt;45&lt;/span&gt; 0,46 &lt;span style="color:#ae81ff"&gt;46&lt;/span&gt; 0,47 &lt;span style="color:#ae81ff"&gt;47&lt;/span&gt; 0,48 &lt;span style="color:#ae81ff"&gt;48&lt;/span&gt; 0,49 &lt;span style="color:#ae81ff"&gt;49&lt;/span&gt; 0,50 &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt; 0,51 &lt;span style="color:#ae81ff"&gt;51&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,52 &lt;span style="color:#ae81ff"&gt;52&lt;/span&gt; 0,53 &lt;span style="color:#ae81ff"&gt;53&lt;/span&gt; 1,54 &lt;span style="color:#ae81ff"&gt;54&lt;/span&gt; 1,55 &lt;span style="color:#ae81ff"&gt;55&lt;/span&gt; 1,56 &lt;span style="color:#ae81ff"&gt;56&lt;/span&gt; 1,57 &lt;span style="color:#ae81ff"&gt;57&lt;/span&gt; 1,58 &lt;span style="color:#ae81ff"&gt;58&lt;/span&gt; 0,59 &lt;span style="color:#ae81ff"&gt;59&lt;/span&gt; 0,60 &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt; 0,61 &lt;span style="color:#ae81ff"&gt;61&lt;/span&gt; 0,62 &lt;span style="color:#ae81ff"&gt;62&lt;/span&gt; 0,63 &lt;span style="color:#ae81ff"&gt;63&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,64 &lt;span style="color:#ae81ff"&gt;64&lt;/span&gt; 1,65 &lt;span style="color:#ae81ff"&gt;65&lt;/span&gt; 1,66 &lt;span style="color:#ae81ff"&gt;66&lt;/span&gt; 1,67 &lt;span style="color:#ae81ff"&gt;67&lt;/span&gt; 1,68 &lt;span style="color:#ae81ff"&gt;68&lt;/span&gt; 1,69 &lt;span style="color:#ae81ff"&gt;69&lt;/span&gt; 1,70 &lt;span style="color:#ae81ff"&gt;70&lt;/span&gt; 1,71 &lt;span style="color:#ae81ff"&gt;71&lt;/span&gt; 0,72 &lt;span style="color:#ae81ff"&gt;72&lt;/span&gt; 0,73 &lt;span style="color:#ae81ff"&gt;73&lt;/span&gt; 0,74 &lt;span style="color:#ae81ff"&gt;74&lt;/span&gt; 0,75 &lt;span style="color:#ae81ff"&gt;75&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 1,76 &lt;span style="color:#ae81ff"&gt;76&lt;/span&gt; 1,77 &lt;span style="color:#ae81ff"&gt;77&lt;/span&gt; 1,78 &lt;span style="color:#ae81ff"&gt;78&lt;/span&gt; 1,79 &lt;span style="color:#ae81ff"&gt;79&lt;/span&gt; 1,80 &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt; 1,81 &lt;span style="color:#ae81ff"&gt;81&lt;/span&gt; 1,82 &lt;span style="color:#ae81ff"&gt;82&lt;/span&gt; 1,83 &lt;span style="color:#ae81ff"&gt;83&lt;/span&gt; 1,84 &lt;span style="color:#ae81ff"&gt;84&lt;/span&gt; 1,85 &lt;span style="color:#ae81ff"&gt;85&lt;/span&gt; 1,86 &lt;span style="color:#ae81ff"&gt;86&lt;/span&gt; 1,87 &lt;span style="color:#ae81ff"&gt;87&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- 0,88 &lt;span style="color:#ae81ff"&gt;88&lt;/span&gt; 0,89 &lt;span style="color:#ae81ff"&gt;89&lt;/span&gt; 0,90 &lt;span style="color:#ae81ff"&gt;90&lt;/span&gt; 0,91 &lt;span style="color:#ae81ff"&gt;91&lt;/span&gt; 0,92 &lt;span style="color:#ae81ff"&gt;92&lt;/span&gt; 0,93 &lt;span style="color:#ae81ff"&gt;93&lt;/span&gt; 0,94 &lt;span style="color:#ae81ff"&gt;94&lt;/span&gt; 0,95 &lt;span style="color:#ae81ff"&gt;95&lt;/span&gt; 1,96 &lt;span style="color:#ae81ff"&gt;96&lt;/span&gt; 1,97 &lt;span style="color:#ae81ff"&gt;97&lt;/span&gt; 1,98 &lt;span style="color:#ae81ff"&gt;98&lt;/span&gt; 99,99 &lt;span style="color:#ae81ff"&gt;99&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :-&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;372&lt;/span&gt; kiwi-n26 :- For more information on using these, see MOTDFORMATTING.md&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.714Z :oragono.test &lt;span style="color:#ae81ff"&gt;376&lt;/span&gt; kiwi-n26 :End of MOTD command&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:07.715Z :oragono.test &lt;span style="color:#ae81ff"&gt;221&lt;/span&gt; kiwi-n26 +Zi&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;WHO kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:15.649Z :oragono.test &lt;span style="color:#ae81ff"&gt;352&lt;/span&gt; kiwi-n26 * ~u gcjc79gmtbe42.irc oragono.test kiwi-n26 H :0 https://kiwiirc.com/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:15.649Z :oragono.test &lt;span style="color:#ae81ff"&gt;315&lt;/span&gt; kiwi-n26 kiwi-n26!*@* :End of WHO list&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;JOIN &lt;span style="color:#75715e"&gt;#kiwiirc-default&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@msgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;bidkvpja5njjtgchub8u65pxgn;time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:26.706Z :kiwi-n26!~u@gcjc79gmtbe42.irc JOIN &lt;span style="color:#75715e"&gt;#kiwiirc-default * https://kiwiirc.com/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:26.706Z :oragono.test &lt;span style="color:#ae81ff"&gt;353&lt;/span&gt; kiwi-n26 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#75715e"&gt;#kiwiirc-default :@kiwi-n28!~u@5g96q93tqw3vn.irc kiwi-n30!~u@5g96q93tqw3vn.irc kiwi-n29!~u@5g96q93tqw3vn.irc kiwi-n26!~u@gcjc79gmtbe42.irc&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:26.706Z :oragono.test &lt;span style="color:#ae81ff"&gt;366&lt;/span&gt; kiwi-n26 &lt;span style="color:#75715e"&gt;#kiwiirc-default :End of NAMES list&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;JOIN &lt;span style="color:#75715e"&gt;#ops&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@msgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;hftqmpu4ieyjybx9bbgf4vpbia;time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:32.145Z :kiwi-n26!~u@gcjc79gmtbe42.irc JOIN &lt;span style="color:#75715e"&gt;#ops * https://kiwiirc.com/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:32.145Z :oragono.test &lt;span style="color:#ae81ff"&gt;353&lt;/span&gt; kiwi-n26 &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#75715e"&gt;#ops :@kiwi-n28!~u@5g96q93tqw3vn.irc kiwi-n30!~u@5g96q93tqw3vn.irc kiwi-n29!~u@5g96q93tqw3vn.irc kiwi-n26!~u@gcjc79gmtbe42.irc&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:55:32.145Z :oragono.test &lt;span style="color:#ae81ff"&gt;366&lt;/span&gt; kiwi-n26 &lt;span style="color:#75715e"&gt;#ops :End of NAMES list&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRIVMSG &lt;span style="color:#75715e"&gt;#ops hello&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRIVMSG &lt;span style="color:#75715e"&gt;#ops :kiwi-n28 good morning&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PRIVMSG kiwi-n28 &lt;span style="color:#f92672"&gt;=&lt;/span&gt;D&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PING kiwitime-1605232555315&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:57:14.150Z :oragono.test PONG oragono.test kiwitime-1605232555315&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHATHISTORY BEFORE kiwi-n28 * &lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:57:38.462Z :oragono.test BATCH +1 chathistory kiwi-n28&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@msgid&lt;span style="color:#f92672"&gt;=&lt;/span&gt;rqdbvmytzppssc5ymp7ffhmkga;time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:56:05.705Z;batch&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; :kiwi-n26!~u@gcjc79gmtbe42.irc PRIVMSG kiwi-n28 :&lt;span style="color:#f92672"&gt;=&lt;/span&gt;D&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:57:38.462Z :oragono.test BATCH -1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2020-11-13T01:59:08.466Z PING kiwi-n26&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;:kiwi-n26!~u@gcjc79gmtbe42.irc QUIT :Ping timeout: 2m30s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ERROR :Ping timeout: 2m30s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Connection closed by foreign host.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以看到这些消息都带有一定的格式，客户端根据特地的格式解析就可以个性化显示来。带有符号@/：前缀的消息都是服务器推送下来的消息，反之都是客户端请求的消息。“CAP LS 302”即协商会话协议版本，随即用命令“NICK ”设置昵称（登录名），和“USER 0 * ”设置该昵称显示的用户名，最后以“CAP END”结束协商，开始会话。服务端推送过来的消息格式为时间戳+服务器+响应码+接受者昵称+消息内容，即“@time=2020-11-13T01:55:07.714Z :oragono.test 001 :Welcome to the Internet Relay Network ”，001代表欢迎信息，具体响应码可以参考&lt;a class="link" href="https://tools.ietf.org/html/rfc2812#section-5.2" target="_blank" rel="noopener"&#10; &gt;这里&lt;/a&gt;。客户端发送消息则直接发送，比如使用“JOIN #channel”加入某个频道，服务器会向该频道里的每个人广播对JOIN应的消息“@msgid=hftqmpu4ieyjybx9bbgf4vpbia;time=2020-11-13T01:55:32.145Z :@gcjc79gmtbe42.irc JOIN #channel * ”并向操作者推送频道用户列表“@time=2020-11-13T01:55:32.145Z :oragono.test 353 = #channel :@!~&lt;a class="link" href="mailto:u@5g96q93tqw3vn.irc" &gt;u@5g96q93tqw3vn.irc&lt;/a&gt; !~&lt;a class="link" href="mailto:u@5g96q93tqw3vn.irc" &gt;u@5g96q93tqw3vn.irc&lt;/a&gt; !~&lt;a class="link" href="mailto:u@5g96q93tqw3vn.irc" &gt;u@5g96q93tqw3vn.irc&lt;/a&gt;&lt;br&gt;&#10;”。Twitch则在消息的基础上加入了其他格式化控制，比如&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@badge-info&lt;span style="color:#f92672"&gt;=&lt;/span&gt;;badges&lt;span style="color:#f92672"&gt;=&lt;/span&gt;premium/1;client-nonce&lt;span style="color:#f92672"&gt;=&lt;/span&gt;2f70a1efd6f84523d0f180cc44f76c61;color&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#75715e"&gt;#B22222;display-name=Khodeine;emotes=58765:9-19;flags=;id=50d8790f-c474-42a8-b873-2d5e8008bd52;mod=0;room-id=30220059;subscriber=0;tmi-sent-ts=1605279854692;turbo=0;user-id=49980352;user-type= :khodeine!khodeine@khodeine.tmi.twitch.tv PRIVMSG #esl_sc2 :the scvs NotLikeThis&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;会显示以一定的颜色/图标显示用户名/消息。空闲状态下IRC服务端与客户端需要维持心跳信息，比如“PING kiwitime-1605232555315”和“time=2020-11-13T01:57:14.150Z :oragono.test PONG oragono.test kiwitime-1605232555315”，否则连接会被关闭。一些常用的命令，可以看出IRC交互非常简单，&lt;a class="link" href="https://en.wikipedia.org/wiki/IRC_services" target="_blank" rel="noopener"&#10; &gt;IRC核心组件&lt;/a&gt;也不多。使用“@+dratf/typing=active TAGMSG ”显示输入状态，借助&lt;a class="link" href="https://tools.ietf.org/id/draft-oakley-irc-ctcp-01.html" target="_blank" rel="noopener"&#10; &gt;CTCP&lt;/a&gt;协议甚至可以点对点发送文件&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#使用password注册当前nickname&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/NS REGISTER &amp;lt;your password&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#注册一个频道&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/CS REGISTER &lt;span style="color:#75715e"&gt;#channelname&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/CS REGISTER &lt;span style="color:#75715e"&gt;#channe&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#要去某人加入频道&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/INVITE nickname &lt;span style="color:#75715e"&gt;#channel&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#给予某个用户频道管理权限&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/mode +o nickname&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#认证成为管理员&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/OPER admin &amp;lt;admin passowrd&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#在频道发送消息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/PRIVMSG &lt;span style="color:#75715e"&gt;#channe hello&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#给频道某人发送消息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/PRIVMSG &lt;span style="color:#75715e"&gt;#channe :&amp;lt;nick&amp;gt; good morning&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#给频道某人发送消息&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/INVITE &amp;lt;nick&amp;gt; &lt;span style="color:#75715e"&gt;#channe&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#使用密码登录&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AUTHENTICATE PLAIN&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AUTHENTICATE +&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;AUTHENTICATE a2l3aS1uMzAAa2l3aS1uMzAAMTAyMDMwNDA&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="link" href="https://thelounge.chat/" target="_blank" rel="noopener"&#10; &gt;Thelounge&lt;/a&gt;是另外一个Vue实现的web的IRC客户端，同样支持websocket。它还用express实现了服务端，支持额外的密码/LDAP登录，即先认证通过才能连接IRC服务器，它本身也可以作为一个服务代理网关，为用户提供永远在线服务/消息存储-如果一个IRC用户不在线是不能够给它发送消息的，这一点也跟XMPP不一样。&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/lounge_join.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="480px" data-flex-grow="200" height="150" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/lounge_join-300x150.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://courages.us/wp-content/uploads/2020/11/lounge_send.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="431px" data-flex-grow="179" height="167" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2020/11/lounge_send-300x167.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;Kiwiirc和Thelounge的设计实现良好，可以作为web chat实现的参考，比如在线客服/销售。比较两个web的IRC客户端发现，他们使用的websocket库并不一样。Kiwiirc使用的是&lt;a class="link" href="https://github.com/sockjs/sockjs-client" target="_blank" rel="noopener"&#10; &gt;sockjs-client&lt;/a&gt;，一个类似websocket的JavaScript网络连接库，支持不同浏览器，能够跨域名通信，在浏览器不支持websocket的情况下退化为&lt;a class="link" href="https://www.pubnub.com/blog/http-long-polling/" target="_blank" rel="noopener"&#10; &gt;polling&lt;/a&gt;（需要&lt;a class="link" href="https://github.com/sockjs/sockjs-node" target="_blank" rel="noopener"&#10; &gt;服务端&lt;/a&gt;配合）。而Thelounge使用的是&lt;a class="link" href="https://github.com/socketio/socket.io" target="_blank" rel="noopener"&#10; &gt;socket.io&lt;/a&gt;。Socket.IO由Engine.IO发展而来，致力于为web提供实时通信能力。Socket.IO并不是WebSocket的一个实现，只是提供了类似的连接能力，需要服务端配合。两个连接库在浏览器支持websocket的情况下都可以直接与websocket服务端通信（不需要对应的库）。Kiwiirc还提供了irc-framework开发库，可以快速搭建一个IRC客户端，比如IRC Bot。至今仍然存在着许多&lt;a class="link" href="https://en.wikipedia.org/wiki/IRC_bot" target="_blank" rel="noopener"&#10; &gt;IRC聊天机器人&lt;/a&gt;，为用户提供方便/服务器报警。Twitch一个用户加入频道时甚至能收到广告！&lt;/p&gt;&#10;&lt;p&gt;Websocket提供了与其他socket一样的能力，能够持续连接和双向通讯，甚至可以服用80/443端口（nginx支持101协议升级）。它不止可以使用在web上，也可以使用在非web上面，因为能够穿透防火墙，对树莓派的远程链接支持。传统的web应用都是一应一答，这节省的服务器/客户端的资源能够不需要持续请求的话。而对于有些应用而言，比如消息通知，希望是能够持续从服务器推送的，websocket增强了它的能力，在这之前都是long polling（所以才有那些包装库）。&lt;br&gt;&#10;Http协议在tcp基础上实现，请求头里面带有host、cookie，url里面带有路径等，这样后端能够识别、路由、分发请求。而tcp并没有这些，websocket必须自己实现类似的路由分发/调用，可以在连接建立初期，鉴别授权（可以在url上面带参数token/jwt/security key），对于后续消息的应答可以在url上面指定，也可以在事件上面指定。这样实现出来似乎与http差不多，仍然有event对应route，但却可以持续交互。&lt;br&gt;&#10;再观察IRC协议也不过是对各个命令的应答，其实也跟经典web MVC差不多-使用URL映射对应的controller/action。IRC每个会话都是一个队列，join #channel命令即订阅消息，part #channel命令则是取消订阅。再看Rabbitmq消息队列，实现了exchange，route，queue，channel，topic等，然后是持续的消费/推送，与前面所诉差不多，这样子看IRC也是个消息服务器。IRC实现简单，通过扩展支持的命令，也能够与内部/外部系统结合，快速搭建一个即时消息平台。&lt;br&gt;&#10;再看邮件服务，其实也是消息服务，也有一对一/群发消息/历史消息，甚至能够给不认识（不在线）的人发送邮件！而邮件服务至今流行，在许多平台，不论服务器还是手机都自带，不需要额外安装软件。&lt;a class="link" href="https://slack.com/intl/en-cn/features" target="_blank" rel="noopener"&#10; &gt;Slack&lt;/a&gt;的产品宣传即对比了自己相对邮件服务的优势。其实手机默认带的电话和短信功能是基于硬件模块的在线功能。&lt;br&gt;&#10;相比Ejabberd/Openfire，IRC服务器的部署简单许多，甚至可以部署在树莓派上！&lt;/p&gt;&#10;&lt;p&gt;参考连接：&lt;br&gt;&#10;&lt;a class="link" href="http://IRC%20bot" target="_blank" rel="noopener"&#10; &gt;IRC Bot&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://developer.ibm.com/zh/technologies/messaging/articles/os-cn-rabbit-mq/" target="_blank" rel="noopener"&#10; &gt;基于 RabbitMQ 的实时消息推送&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>TCP UDP探索</title><link>https://courages.us/tcp-udp%E6%8E%A2%E7%B4%A2/</link><pubDate>Sat, 03 Dec 2016 16:19:12 +0800</pubDate><guid>https://courages.us/tcp-udp%E6%8E%A2%E7%B4%A2/</guid><description>&lt;p&gt;最近开发新接口，为实现更高的性能，深入考察了下TCP，UDP通信协议。之前的开发当中都是基于HTTP的接口开发，简单易用，各个编程语言都支持；web服务器、中间件成熟，方便扩展；支持安全加密等等。与自定义Socket通信相比，HTTP仍然不够高效。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://zh.wikipedia.org/wiki/%E4%BC%A0%E8%BE%93%E6%8E%A7%E5%88%B6%E5%8D%8F%E8%AE%AE" target="_blank" rel="noopener"&#10; &gt;TCP协议&lt;/a&gt;，也叫传输控制协议（Transmission Control Protocol）是一种面向连接的、可靠的、基于字节流的传输层通信协议。每建立一个TCP连接需要三次握手，关闭时又需要四次握手；传输过程当中，每发送一个包，都要接收一个确认回复，如果在一定时间内未收到，则重发，如果是同一块数据分包传输，则回复所需要的包序号；在发送和接收时都要计算校验和。由于有严格的数据包传输顺序和校验，因为接收到的数据将会是顺序。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://zh.wikipedia.org/wiki/%E7%94%A8%E6%88%B7%E6%95%B0%E6%8D%AE%E6%8A%A5%E5%8D%8F%E8%AE%AE" target="_blank" rel="noopener"&#10; &gt;UDP协议&lt;/a&gt;，也叫用户数据报协议（User Datagram Protocol）是一个简单的面向数据报的传输层协议。它只管数据包发送，并不没有TCP的连接控制、回复确认，并不知道对方是否接收成功。因为并不等待接收方回复，发送端可以连续发送数据，接收端接收到数据并不一定是顺序的。因此相比TCP，UDP的有更高的传输效率，更低的可靠性。如果需要可靠性，则需要发送确认包，类似TCP那样子。&lt;/p&gt;&#10;&lt;p&gt;通常&lt;a class="link" href="https://zh.wikipedia.org/wiki/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE" target="_blank" rel="noopener"&#10; &gt;HTTP协议&lt;/a&gt;基于TCP实现，保证收到的内容是完整、顺序的。在HTTP 1.0时，每一次请求都需要建立TCP连接，关闭TCP连接；在HTTP 1.1时，同一TCP连接则可以在活跃（Keep-Live）间期内复用。HTTP是无连接的，每次处理完成请求即断开连接，一方面可以节省服务器资源，另一方面却浪费连接时间。如果需要维持客户端的Keep-Alive状态，则又需要消耗更多服务器资源，需要权衡。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://zh.wikipedia.org/wiki/WebSocket" target="_blank" rel="noopener"&#10; &gt;WebSocket&lt;/a&gt;是基于TCP 连接上进行全双工通讯的协议，允许服务端直接向浏览器发送消息，不再需要ajax轮询。它也是&lt;a class="link" href="http://stackoverflow.com/questions/35315641/can-tcp-udp-sockets-and-websockets-communicate-with-each-other" target="_blank" rel="noopener"&#10; &gt;在TCP上面的实现&lt;/a&gt;，使用类似HTTP请求的握手协议，进行TCP通信切换。&lt;a class="link" href="https://zh.wikipedia.org/wiki/WebRTC" target="_blank" rel="noopener"&#10; &gt;WebRTC&lt;/a&gt;，也叫Web即时通信（Web Real-Time Communication），则是一个支持浏览器之间进行实时语音对话或视频对话的API。它是建立于TCP/UDP之上的点对点通信，客户端基于上层&lt;a class="link" href="https://www.html5rocks.com/en/tutorials/webrtc/datachannels/" target="_blank" rel="noopener"&#10; &gt;RTCDataChannel&lt;/a&gt;进行通信而非底层TCP/UDP。&lt;/p&gt;&#10;&lt;p&gt;Google推出了基于UDP的&lt;a class="link" href="https://zh.wikipedia.org/wiki/QUIC" target="_blank" rel="noopener"&#10; &gt;QUIC协议（快速UDP网络连接）&lt;/a&gt;实现的HTTP传输，可以快速在两个端点间创建连接，支持多路复用连接。对于丢包问题，则采用冗余传输，能够根据接收到的包，对缺失的包进行恢复（类似RAID）。对于一个TCP连接，需要四个参数：源IP/端口，目的IP/端口，任何一个改变都需要重新建立连接。QUIC则不需要这些，因为UDP并不需要来源信；它使用UUID来标识一个连接，只要这个UUID在，那么这个连接会话就能够继续（与HTTP会话有点像）。因此在不同网络，特别是移动网络之间的切换，都将保持稳定（参考：&lt;a class="link" href="http://Mosh" target="_blank" rel="noopener"&#10; &gt;Mosh&lt;/a&gt;）。目前Google的网站已经支持，并可以在Chrome浏览器的里面查看连接情况：chrome://net-internals/#quic。&lt;/p&gt;&#10;&lt;p&gt;通常说TCP是可靠连接，可用于数据流，复杂网络情况；UDP由于缺少确认机制等，属不可靠连接，通常应用于网络情况良好（内部）或者允许丢包的场景。事实上UDP也应用于游戏，VoIP等需要高效传输的场景。当网络状况糟糕时，使用TCP通信反而可能更差，因为需要更多步骤建立连接和确认。参考这里：&lt;a class="link" href="https://www.zhihu.com/question/20292749" target="_blank" rel="noopener"&#10; &gt;QQ 为什么采用 UDP 协议，而不采用 TCP 协议实现？&lt;/a&gt;。TCP连接是有状态的，服务端需要去维持，及&lt;a class="link" href="http://huoding.com/2013/12/31/316" target="_blank" rel="noopener"&#10; &gt;TIME_WAIT&lt;/a&gt;问题。如果连接一段时间没用，TCP并不能感知连接是否仍然有效，需要自定义心跳包，维持连接。UDP则是无连接状态的，只要知道目标IP及端口即可以发送。&lt;/p&gt;&#10;&lt;p&gt;UDP通信简单许多，不需要socket_connect和socket_connect，主动暴露一端（服务端）需要socket_bind。例如，服务端：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$socket &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_socket_server&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;udp://127.0.0.1:1113&amp;#34;&lt;/span&gt;, $errno, $errstr, &lt;span style="color:#a6e22e"&gt;STREAM_SERVER_BIND&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$socket) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;die&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;$errstr&lt;/span&gt;&lt;span style="color:#e6db74"&gt; (&lt;/span&gt;&lt;span style="color:#e6db74"&gt;$errno&lt;/span&gt;&lt;span style="color:#e6db74"&gt;)&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $pkt &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_socket_recvfrom&lt;/span&gt;($socket, &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, $peer);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;echo&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#e6db74"&gt;$peer&lt;/span&gt;&lt;span style="color:#e6db74"&gt;,&lt;/span&gt;&lt;span style="color:#e6db74"&gt;$pkt&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//客户端互相通信时，注释下面一行&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;stream_socket_sendto&lt;/span&gt;($socket, &lt;span style="color:#a6e22e"&gt;date&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;D M j H:i:s Y&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\r\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;), &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, $peer);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; ($pkt &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;客户端：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$sock &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_create&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;AF_INET&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;SOCK_DGRAM&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;SOL_UDP&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$msg &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Ping !&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$len &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strlen&lt;/span&gt;($msg);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;socket_sendto&lt;/span&gt;($sock, $msg, $len, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1113&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//sleep(30)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$res &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_recv&lt;/span&gt;( $sock , $reply , &lt;span style="color:#ae81ff"&gt;2045&lt;/span&gt; , &lt;span style="color:#a6e22e"&gt;MSG_WAITALL&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;echo&lt;/span&gt; $reply;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;socket_close&lt;/span&gt;($sock);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;服务端的代码里面有个stream_socket_sendto（或者socket_sendto），向客户端发送消息。UDP并不需要向客户端回复消息，这并像TCP在同一个连接里面回复，而是另一次UDP通信罢了。实际上，两个客户端之间就能够互相通信（分别使用不同端口），任何能够拿到对方IP和端口，都能够向其发送消息。复制客户端代码，更改目标IP和端口为服务端打印出来的信息，然后运行，原先的客户端也将收到消息。利用中间服务器交换两个客户端的IP和端口，以便直接通信，是NAT穿透常用的方法。&lt;/p&gt;&#10;&lt;p&gt;综上，使用TCP可以保证数据可靠传输，复用连接，比如请求-应答模型；使用UDP则可以更高效发送数据，但能容忍部分丢包的场景，比如视频画面；或者只发送不需响应的数据，比如日志；或者无需连接状态的场景（类似HTTP会话），减少服务器压力和客户端等待。当然，也可以在UDP基础上自定义传输规则，实现譬如Mosh或则TCP那样的应用。选择TCP或者UDP，应该综合考虑使用场景，网络，数据包大小，效率，安全等，而不是盲从字面上的“面向可靠的”或者“不可靠的”或者“高效的”。&lt;/p&gt;&#10;&lt;p&gt;参考链接：&lt;br&gt;&#10;&lt;a class="link" href="http://blog.csdn.net/tennysonsky/article/details/44562435" target="_blank" rel="noopener"&#10; &gt;如何理解HTTP协议的 “无连接，无状态” 特点？&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://ma.ttias.be/googles-quic-protocol-moving-web-tcp-udp/" target="_blank" rel="noopener"&#10; &gt;Google’s QUIC protocol: moving the web from TCP to UDP（&lt;/a&gt;&lt;a class="link" href="http://www.infoq.com/cn/articles/quic-google-protocol-web-platform-from-tcp-to-udp" target="_blank" rel="noopener"&#10; &gt;Google QUIC协议：从TCP到UDP的Web平台&lt;/a&gt;）&lt;br&gt;&#10;&lt;a class="link" href="http://zhihu.com/question/29705994/answer/46357120" target="_blank" rel="noopener"&#10; &gt;如何看待谷歌 Google 打算用 QUIC 协议替代 TCP/UDP？ – 回答作者: Trotyl Yu&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://mosh.org/#techinfo" target="_blank" rel="noopener"&#10; &gt;How Mosh works&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.cnblogs.com/regedit/articles/829725.html" target="_blank" rel="noopener"&#10; &gt;使用TCP协议的NAT穿透技术&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/php-socket%e9%80%9a%e4%bf%a1/" target="_blank" rel="noopener"&#10; &gt;PHP Socket通信&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/http%e6%96%87%e4%bb%b6%e5%88%86%e5%9d%97%e4%b8%8a%e4%bc%a0%e4%b8%8b%e8%bd%bd/" target="_blank" rel="noopener"&#10; &gt;日志系统设计&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://blog.codingnow.com/2016/03/reliable_udp.html" target="_blank" rel="noopener"&#10; &gt;可靠 UDP 传输&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://zh.wikipedia.org/wiki/%E9%98%BB%E6%96%B7%E6%9C%8D%E5%8B%99%E6%94%BB%E6%93%8A" target="_blank" rel="noopener"&#10; &gt;DDOS（拒绝服务攻击）&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://blog.csdn.net/blognkliming/article/details/17181773" target="_blank" rel="noopener"&#10; &gt;php使用socket感悟–tcp和udp&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.binarytides.com/udp-socket-programming-in-php/" target="_blank" rel="noopener"&#10; &gt;UDP socket programming in php&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://stackoverflow.com/questions/18897917/does-webrtc-use-tcp-or-udp" target="_blank" rel="noopener"&#10; &gt;Does WebRTC use TCP or UDP?&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>PHP ZeroMQ开发</title><link>https://courages.us/php-zeromq/</link><pubDate>Fri, 10 Jul 2015 17:30:31 +0800</pubDate><guid>https://courages.us/php-zeromq/</guid><description>&lt;p&gt;&lt;a class="link" href="http://zeromq.org/" target="_blank" rel="noopener"&#10; &gt;ZeroMQ&lt;/a&gt;的名字有点巧妙，看起来是个MQ却加了个0，变得不是MQ。ZeroMQ是一个面向消息传递的网络通信框架，支持程序在进程内部部通信，进程之间通信，网络间通信，多播等。ZeroMQ对Socket进行了封装，支持多种网络结构范式如Request/Reply，Pub/Sub，Pull/Push，中介，路由等，还可以在这些模式再次扩展，动态扩容程序和分布式任务开发，能够轻易搭建服务程序集群。&lt;/p&gt;&#10;&lt;p&gt;ZeroMQ与支持AMQP的消息中间件不一样，ZeroMQ是一个网络通信库，需要自行实现中间节点和消息的管理。&lt;/p&gt;&#10;&lt;p&gt;在CentOS安装ZeroMQ4&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone https://github.com/zeromq/zeromq4-x.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd zeromq4-x&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./autogent.sh&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./configure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo make&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo make install&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#声明libzmq库的位置&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo vim /etc/ld.so.conf.d/libzmq.conf&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#内容：/usr/local/lib&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo ldconfig&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ZeroMQ支持多种编程语言，也包括PHP。php-zmq安装&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone https://github.com/mkoppanen/php-zmq.git&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd php-zmq&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;phpize&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./configure&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo make&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo make install&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo vim /etc/php.ini&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;编辑PHP.ini增加扩展信息&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[zeromq]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;extension = zmq.so&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;查看扩展是否加载成功：php -m | grep php。&lt;br&gt;&#10;先写一个简单请求-应答，首先是服务端reply.php&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_REP&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://*:5559&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;echo&lt;/span&gt; $strMessage&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\r\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;From Server1:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;$strMessage);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后是客户端request.php&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_REQ&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://localhost:5559&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello From Client:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;uniqid&lt;/span&gt;());&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;var_dump&lt;/span&gt;($pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;());&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;分别在不同终端预先一下程序&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#请求者可以先启动&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php request.php&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#另一个终端&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php reply.php&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用ZeroMQ进行通信的步骤&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;使用ZMQContext创建一个上下文&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;使用上下文初始化ZMQSocket，这里需要指明socket类型（ZMQ::SOCKET_开头），组合模式包括&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;PUB，SUB&lt;/li&gt;&#10;&lt;li&gt;REQ，REP&lt;/li&gt;&#10;&lt;li&gt;REQ，ROUTER (take care, REQ inserts an extra null frame)&lt;/li&gt;&#10;&lt;li&gt;DEALER，REP (take care, REP assumes a null frame)&lt;/li&gt;&#10;&lt;li&gt;DEALER，ROUTER&lt;/li&gt;&#10;&lt;li&gt;DEALER，DEALER&lt;/li&gt;&#10;&lt;li&gt;ROUTER，ROUTER&lt;/li&gt;&#10;&lt;li&gt;PUSH，PULL&lt;/li&gt;&#10;&lt;li&gt;PAIR，PAIR&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;分类包括&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;轮询，REQ，PUSH，DEALER&lt;/li&gt;&#10;&lt;li&gt;多播，PUB&lt;/li&gt;&#10;&lt;li&gt;公平排队，REP，SUB，PULL，DEALER&lt;/li&gt;&#10;&lt;li&gt;明确寻址，ROUTER&lt;/li&gt;&#10;&lt;li&gt;单播，PAIR&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;如果是服务端就bind，如果是客户端就conncet，这里的连接信息支持&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;进程内部通信，inproc://&lt;/li&gt;&#10;&lt;li&gt;进程间通信，ipc://&lt;/li&gt;&#10;&lt;li&gt;网络间通信，tcp://&lt;/li&gt;&#10;&lt;li&gt;多播，pgm://&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;使用send/recv发送/接收消息&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;使用ZeroMQ创建通信比socket简单多了，与stream_socket差不多。但是使用ZeroMQ，客户端可以先启动而不用管服务端是否已经启动了，等服务端连接上了便会自动传递消息，还可以维持节点之间的心跳。&lt;/p&gt;&#10;&lt;p&gt;ZeroMQ与socket通信是不一样的。ZeroMQ是无状态的，对socket的细节进行了封装，不能知道彼此的socket连接信息，仅能接收和发送消息；ZeroMQ能够使用一个socket与多个节点进行通信，具有极高的性能。&lt;/p&gt;&#10;&lt;p&gt;再回头看一下服务端程序，这里采用while循环来处理，亦即同一时刻只能处理一个请求，多个请求排队直到被轮询到，客户端的发送和接收都是同步等待。由于不知道客户端信息，也不能在子进程内处理完成再返回。这里就需要用到ZeroMQ各种范式的组合，比如下面这个&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2015/07/fig16.png" target="_blank" rel="noopener"&#10; &gt;&lt;img alt="fig16" class="gallery-image" data-flex-basis="250px" data-flex-grow="104" height="287" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2015/07/fig16-300x287.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;这里使用ROUTER和DEALER作为中介，转发请求，客户端可以异步发送求，不用等待服务端响应。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pFrontend &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_ROUTER&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pBackend &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_DEALER&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pFrontend&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://*:5559&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pBackend&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://*:5560&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPoll &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQPoll&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPoll&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;($pFrontend, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;POLL_IN&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPoll&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;($pBackend, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;POLL_IN&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$arrRead &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $arrWrite &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;$nEvent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pPoll&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;poll&lt;/span&gt;($arrRead, $arrWrite);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ($nEvent &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;foreach&lt;/span&gt;($arrRead &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; $pSocket){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($pSocket &lt;span style="color:#f92672"&gt;===&lt;/span&gt; $pFrontend){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pSocket&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;$nMore &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pSocket&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;getSockOpt&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKOPT_RCVMORE&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;$pBackend&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;($strMessage,$nMore &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;MODE_SNDMORE&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$nMore){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ($pSocket &lt;span style="color:#f92672"&gt;===&lt;/span&gt; $pBackend){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pSocket&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;$nMore &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pSocket&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;getSockOpt&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKOPT_RCVMORE&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;$pFrontend&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;($strMessage,$nMore &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;MODE_SNDMORE&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$nMore){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后更改服务端reply.php，不再绑定监听，而不是连接到DEALER上&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_REP&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$pServer-&amp;gt;bind(&amp;#34;tcp://*:5555&amp;#34;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://localhost:5560&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;echo&lt;/span&gt; $strMessage&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\r\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;From Server1:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;$strMessage);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里使用ZMQPoll对ZMQSOcket的输入输出事件进行轮询，将ROUTER收到的REQ转发给服务端，将DEALER收到的REP转发给客户端。事实上，还有更简便的方法：使用ZMQDevice将ROUTER和DEALER组合起来&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pFrontend &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_ROUTER&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pBackend &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_DEALER&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pFrontend&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://*:5559&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pBackend&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://*:5560&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pDevice &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQDevice&lt;/span&gt;($pFrontend, $pBackend);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pDevice&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ZeroMQ的Pub/Sub的通信模型支持一个发布者发布消息给多个订阅者，也支持一个订阅者从多个发布者订阅消息。首先写一个发布者&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPublisher &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_PUB&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPublisher&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://*:5563&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $pPublisher&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;MODE_SNDMORE&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $pPublisher&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;1:We don&amp;#39;t want to see this&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $pPublisher&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;B&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;MODE_SNDMORE&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $pPublisher&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;1:We would like to see this&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;sleep&lt;/span&gt; (&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后是订阅者&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pSubscriber &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_SUB&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pSubscriber&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://localhost:5563&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#可以连接多个发布者&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pSubscriber&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://localhost:5564&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pSubscriber&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;setSockOpt&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKOPT_SUBSCRIBE&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;B&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Read envelope with address&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $address &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pSubscriber&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Read message contents&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $contents &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pSubscriber&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt; (&lt;span style="color:#e6db74"&gt;&amp;#34;[%s] %s%s&amp;#34;&lt;/span&gt;, $address, $contents, &lt;span style="color:#a6e22e"&gt;PHP_EOL&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pub/Sub模型，发布者只能发布消息，要求发布消息前，先声明主题（地址），然后发布消息内容；订阅者只能接收消息，先设置订阅主题，然后两次接收，第一次为消息主题，第二次为消息内容。&lt;br&gt;&#10;Pub/Sub模型通消息为单向流动，可以结合其他模型让订阅者与发布者互动，比如REQ\REP。&lt;/p&gt;&#10;&lt;p&gt;ZeroMQ的Push/Pull模型，生产者负责推送消息，消费者负责拉取消息。初看之下Pull/Push模型与Pub/sub模型类似，但是Pull/Push下生产者产生的消息只会投递给一个消费者，并不会发布给全部消费者，适合用于任务投递分配&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2015/07/fig5.png" target="_blank" rel="noopener"&#10; &gt;&lt;img alt="fig5" class="gallery-image" data-flex-basis="180px" data-flex-grow="75" height="300" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2015/07/fig5-225x300.png" width="225"&gt;&lt;/a&gt;&lt;br&gt;&#10;Push和Pull都既可作为服务端，也可作为客户端。服务端Push.php&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPush &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_PUSH&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPush&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://*:5558&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$pPush-&amp;gt;connect(&amp;#34;tcp://localhost:5558&amp;#34;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$pPush-&amp;gt;connect(&amp;#34;tcp://localhost:5559&amp;#34;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPush&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello Client 1&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;客户端Pull.php&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPull &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_PULL&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$pPull-&amp;gt;bind(&amp;#34;tcp://*:5558&amp;#34;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPull&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://localhost:5558&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pPull&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://localhost:5559&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;var_dump&lt;/span&gt;($pPull&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;());&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果同时启动了两个客户端Pull.php，而只启动一个服务端Push.php，那么一次只会有一个客户端接收到消息。也可以以Pull作为主动监听，Push作为被动连接。可以同时接可以Pub/Sub和Pull/Push来处理任务&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2015/07/fig56.png" target="_blank" rel="noopener"&#10; &gt;&lt;img alt="fig56" class="gallery-image" data-flex-basis="210px" data-flex-grow="87" height="300" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2015/07/fig56-263x300.png" width="263"&gt;&lt;/a&gt;&lt;br&gt;&#10;如果是用ZeroMQ传递消息收不到，可以按下面这个流程查问题&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2015/07/chapter1_9.png" target="_blank" rel="noopener"&#10; &gt;&lt;img alt="chapter1\\_9" class="gallery-image" data-flex-basis="104px" data-flex-grow="43" height="300" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2015/07/chapter1_9-131x300.png" width="131"&gt;&lt;/a&gt;&lt;br&gt;&#10;除了客户端可以连接多个服务端，服务端同样可以绑定多个地址。在REQ/REP模型里，让服务端同时使用IPC（进程间通信）来处理本机的连接&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_REP&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;tcp://*:5556&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;ipc:///tmp/req.ipc&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;$message &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;echo&lt;/span&gt; $message &lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;PHP_EOL&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello from server1:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;$message);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;客户端可以选择走TCP或者IPC进行消息通信&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pContext &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;($pContext, &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_REQ&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;ipc:///tmp/req.ipc&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$pClient-&amp;gt;connect(&amp;#34;tcp://localhost:5556&amp;#34;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello From Client1:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;uniqid&lt;/span&gt;());&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;echo&lt;/span&gt; $strMessage,&lt;span style="color:#a6e22e"&gt;PHP_EOL&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用ZeroMQ的进程内部消息通信也很简单&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;(), &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_REP&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bind&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;inproc://reply&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQSocket&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ZMQContext&lt;/span&gt;(), &lt;span style="color:#a6e22e"&gt;ZMQ&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;SOCKET_REQ&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;inproc://reply&amp;#34;&lt;/span&gt;);;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello From Client1:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;uniqid&lt;/span&gt;());&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;var_dump&lt;/span&gt;($pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;());&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ZeroMQ为消息传递的提供极简的方法，提供了各种连接模型，可以自由扩展。&lt;a class="link" href="http://zguide.zeromq.org/php:all" target="_blank" rel="noopener"&#10; &gt;zguide&lt;/a&gt;更像是一个网络编程指南，指导大家如何利用ZeroMQ搭建各种网络通信模式，提高程序扩展性和健壮性。虽然ZeroMQ解决了进程间和网络间的通信问题，但是各个组件本身进程控制仍然需要自行实现。&lt;/p&gt;&#10;&lt;p&gt;更新：ZeroMQ的作者用C语言创建了另外一个支持多种通用通信范式的socket库：&lt;a class="link" href="http://nanomsg.org/" target="_blank" rel="noopener"&#10; &gt;nanomsg&lt;/a&gt;，可以用来代替ZeroMQ做的那些事，提供了更好的伸缩性，也有对应的&lt;a class="link" href="https://github.com/mkoppanen/php-nano" target="_blank" rel="noopener"&#10; &gt;PHP扩展&lt;/a&gt;。&lt;/p&gt;&#10;&lt;p&gt;参考链接：&lt;br&gt;&#10;&lt;a class="link" href="https://github.com/anjuke/zguide-cn" target="_blank" rel="noopener"&#10; &gt;ZMQ 指南&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.slideshare.net/josezap1/zero-mq-and-cakephp" target="_blank" rel="noopener"&#10; &gt;ZeroMQ in PHP&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.slideshare.net/IanBarber/zeromq-is-the-answer" target="_blank" rel="noopener"&#10; &gt;zeromq is the answer&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://toys.lerdorf.com/archives/57-ZeroMQ-&amp;#43;-libevent-in-PHP.html" target="_blank" rel="noopener"&#10; &gt;ZeroMQ + libevent in PHP&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.slideshare.net/fcrippa/europycon2011-implementing-distributed-application-using-zeromq" target="_blank" rel="noopener"&#10; &gt;Europycon2011: Implementing distributed application using ZeroMQ&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://tim.dysinger.net/posts/2013-09-16-getting-started-with-nanomsg.html" target="_blank" rel="noopener"&#10; &gt;Getting Started with ‘nanomsg’&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://bravenewgeek.com/a-look-at-nanomsg-and-scalability-protocols/" target="_blank" rel="noopener"&#10; &gt;A Look at Nanomsg and Scalability Protocols (Why ZeroMQ Shouldn’t Be Your First Choice)&lt;/a&gt;&lt;/p&gt;&#10;</description></item><item><title>PHP Socket通信</title><link>https://courages.us/php-socket%E9%80%9A%E4%BF%A1/</link><pubDate>Sun, 05 Jul 2015 23:32:42 +0800</pubDate><guid>https://courages.us/php-socket%E9%80%9A%E4%BF%A1/</guid><description>&lt;p&gt;前一篇介绍了跨语言的服务调用框架&lt;a class="link" href="https://courages.us/php-rpc%e5%bc%80%e5%8f%91%e4%b9%8bthrift/" target="_blank" rel="noopener"&#10; &gt;Thrift&lt;/a&gt;，模块与模块之间调用，网络通信必不可少。这里具体介绍下如何使用PHP socket客户端与服务端进行通信。&lt;/p&gt;&#10;&lt;p&gt;PHP 的Socket扩展是基于流行的BSD sockets，实现了和socket通讯功能的底层接口，它可以和通用客户端一样当做一个socket服务器。这里的通用客户端是指stream_socket_*系列封装的函数。&lt;/p&gt;&#10;&lt;p&gt;首先写一个socket服务端&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServerSocket&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $strHost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $nPort &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2015&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $nProtocol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SOL_TCP&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $pSocket &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $pClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; $strErrorCode &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; $strErrorMsg &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__construct&lt;/span&gt;($p_strHost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;, $p_nPort &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2015&lt;/span&gt;, $p_nProtocol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SOL_TCP&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//参数验证&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strHost&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_strHost;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nPort&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_nPort;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nProtocol&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_nProtocol;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_create&lt;/span&gt;()&lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_bind&lt;/span&gt;()){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_listen&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_create&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_create&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;AF_INET&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;SOCK_STREAM&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nProtocol&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_bind&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_bind&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strHost&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nPort&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$bRes){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $bRes;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_listen&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_listen&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;) ;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$bRes){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $bRes;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;accept&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_accept&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;accept&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;socket_getpeername&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, $address, $port)){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;echo&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Client &lt;/span&gt;&lt;span style="color:#e6db74"&gt;$address&lt;/span&gt;&lt;span style="color:#e6db74"&gt; : &lt;/span&gt;&lt;span style="color:#e6db74"&gt;$port&lt;/span&gt;&lt;span style="color:#e6db74"&gt; is now connected to us. &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;hello world from server&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_reply&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$mxData &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;var_dump&lt;/span&gt;($mxData);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ($mxData &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;socket_close&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;echo&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;client disconnected.&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Client: &amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;trim&lt;/span&gt;($mxData)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;($strMessage);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_reply&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$mxMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_read&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;PHP_BINARY_READ&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($mxMessage &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $mxMessage;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;($p_strMessage){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_write&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, $p_strMessage, &lt;span style="color:#a6e22e"&gt;strlen&lt;/span&gt; ($p_strMessage));&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$bRes){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $bRes;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_close&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorCode&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_last_error&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorMsg&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_strerror&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorCode&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//throw new Exception(&amp;#34;exception:&amp;#34;.$this-&amp;gt;strErrorMsg , $this-&amp;gt;strErrorCode);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__destruct&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strHost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$nPort &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25003&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strProtocol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServerSocket&lt;/span&gt;($strHost, $nPort);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里对socket_*系列函数进行了包装，创建socket服务端的步骤&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;使用&lt;a class="link" href="http://php.net/manual/zh/function.socket-create.php" target="_blank" rel="noopener"&#10; &gt;socket_create&lt;/a&gt;创建socket（套接字）。第一个参数AF_INET指IPV4网络协议，TCP和UDP均可使用，对应IPV6网络协议为AF_INET6，也可以使用UNIX socket协议AF_UNIX，作进程间通信&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;。第二个参数对应套接字类型，SOCK_STREAM对应TCP协议使用，SOCK_DGRAM对应UDP协议使用，还有SOCK_SEQPACKET，SOCK_RAW，SOCK_RDM等类型。第三个为协议类型，TCP协议对应常量SOL_TCP，UDP协议对应常量SOL_UDP，其他协议可以从getprotobyname函数获取。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;使用socket_bind将套接字绑定到对应的主机端口或者UNIX socket上&lt;/li&gt;&#10;&lt;li&gt;使用socket_listen监听该套接字上的连接&lt;/li&gt;&#10;&lt;li&gt;使用socket_accept接收套接字上的请求连接，返回一个新的套接字用于与客户端通信。如果没有连接接入，将会阻塞住；如果有多个连接，使用第一个达到的连接。&lt;/li&gt;&#10;&lt;li&gt;开始通信，使用socket_read获取请求信息，使用socket_write返回响应结果&lt;/li&gt;&#10;&lt;li&gt;使用socket_close关闭连接，包括原始的和socket_accept产生的套接字&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这个过程中，可以使用socket_last_error和socket_strerror获取错误信息。接着创建客户端&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ClientSocket&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $strHost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $nPort &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2015&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $nProtocol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SOL_TCP&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; $pSocket &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; $strErrorCode &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; $strErrorMsg &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__construct&lt;/span&gt;($p_strHost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;, $p_nPort &lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2015&lt;/span&gt;, $p_nProtocol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SOL_TCP&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//参数验证&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strHost&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_strHost;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nPort&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_nPort;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nProtocol&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_nProtocol;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_create&lt;/span&gt;()){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_create&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_create&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;AF_INET&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;SOCK_STREAM&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nProtocol&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$pSocket &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_create&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_connect&lt;/span&gt;($pSocket, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strHost&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nPort&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$bRes){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $bRes;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$strBuffer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; ($strBuffer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_read&lt;/span&gt; ($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;PHP_BINARY_READ&lt;/span&gt;)) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$strMessage &lt;span style="color:#f92672"&gt;.=&lt;/span&gt; $strBuffer;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $strMessage;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;($p_strMessage){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_write&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;, $p_strMessage, &lt;span style="color:#a6e22e"&gt;strlen&lt;/span&gt;($p_strMessage));&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$bRes){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;send&lt;/span&gt;($p_strMessage){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_send&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt; , $p_strMessage , &lt;span style="color:#a6e22e"&gt;strlen&lt;/span&gt;($p_strMessage) , &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$bRes){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;recv&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$strBuffer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_recv&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;, $strBuffer, &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt; , &lt;span style="color:#a6e22e"&gt;MSG_WAITALL&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$bRes){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$strMessage &lt;span style="color:#f92672"&gt;.=&lt;/span&gt;$strBuffer;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $strMessage;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_close&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_log&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorCode&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_last_error&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorMsg&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket_strerror&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorCode&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//throw new Exception(&amp;#34;exception:&amp;#34;.$this-&amp;gt;strErrorMsg , $this-&amp;gt;strErrorCode);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__destruct&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strHost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$nPort &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25003&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strProtocol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$nProtocol = getprotobyname($strProtocol);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ClientSocket&lt;/span&gt;($strHost, $nPort);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;var_dump&lt;/span&gt;($pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;());&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;Some Thing :&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;uniqid&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;var_dump&lt;/span&gt;($strMessage);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;($strMessage);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;var_dump&lt;/span&gt;($pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;());&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/*&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt; var_dump($pClient-&amp;gt;recv());&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;$pClient-&amp;gt;send(&amp;#39;hello&amp;#39;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;var_dump($pClient-&amp;gt;recv());&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;*/&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;客户端的创建步骤:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;使用socket_create创建socket套接字，与服务端对应&lt;/li&gt;&#10;&lt;li&gt;使用socket_connect连接到服务端的地址或UNIX socket&lt;/li&gt;&#10;&lt;li&gt;开始通信，可以使用socket_write和socket_read向套接字写入和读取信息，也可以使用socket_send和socket_recv发送和接收信息&lt;/li&gt;&#10;&lt;li&gt;使用socket_close关闭连接&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;运行服务端程序&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php serversocket.php&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在另一个终端里运行&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant socket&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# netstat -apn | grep 25003&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 127.0.0.1:25003 0.0.0.0:* LISTEN 12139/php&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果运行服务端失败，提示 socket_bind(): unable to bind address [98]: Address already in use ，则是端口绑定失败。查看端口占用&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;root@vagrant socket&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&lt;span style="color:#75715e"&gt;# netstat -apn | grep 25003&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tcp &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; 127.0.0.1:25003 127.0.0.1:36618 TIME_WAIT -&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;该端口处于TIME_WAIT状态，需要再等一会儿才会释放。这是因为TCP连接关闭需要四次握手，服务端主动关闭了连接，但是未收到客户端发过来的关闭确认，导致处于等待状态，具体原因见火丁笔记&lt;a class="link" href="http://huoding.com/2013/12/31/316" target="_blank" rel="noopener"&#10; &gt;《再叙TIME_WAIT》&lt;/a&gt;。&lt;/p&gt;&#10;&lt;p&gt;如果服务端已经运行成功，在另一个终端里运行客户端程序&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php clientsocket.php&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这是一个简单服务端/客户端请求应答模型，通常服务端会一直处于监听状态，处理新的请求，重新写一个循环监听的服务端&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SelectServerSocket&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServerSocket&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;loop&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;loop&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrRead &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrWrite &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $arrExp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$arrRead &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $arrClient;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;socket_select&lt;/span&gt;($arrRead, $arrWrite, $arrExp, &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;foreach&lt;/span&gt; ($arrRead &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; $pSocket){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($pSocket &lt;span style="color:#f92672"&gt;==&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;$arrClient[] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_reply&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($bRes &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&#9;$nKey &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;array_search&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, $arrClient);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;unset&lt;/span&gt;($arrClient[$nKey]);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//usleep(100);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strHost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$nPort &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25003&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strProtocol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SelectServerSocket&lt;/span&gt;($strHost, $nPort);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在循环里面使用&lt;a class="link" href="http://php.net/manual/zh/function.socket-select.php" target="_blank" rel="noopener"&#10; &gt;socket_select&lt;/a&gt;查询有可以读的套接字，如果套接字为原始监听的套接字，则使用socket_accept获取新接入的通信套接字进行通信；如果是通信套接字，则与客户端进行交互。&lt;/p&gt;&#10;&lt;p&gt;这里socket_select($arrRead, $arrWrite, $arrExp, null)的第四个参数为null，表示可以无限阻塞，如果为0则不阻塞立即返回，其他大于0值则等待超时。&lt;br&gt;&#10;socket_recv($this-&amp;gt;pSocket, $strBuffer, 1024 , MSG_WAITALL)的第四个参数为MSG_WAITALL，表示阻塞读取结果。&lt;br&gt;&#10;socket_read ($this-&amp;gt;pSocket, 1024, PHP_BINARY_READ )的第三个参数PHP_BINARY_READ表示读取以\0结束，PHP_NORMAL_READ表示读取以\n或\r结束&lt;/p&gt;&#10;&lt;p&gt;在终端里运行服务端，会一直在那里等待新的连接。这时候运行客户端，客户端确也阻塞住了。解决的办法有两种：超时设置和非阻塞设置。给ClientSocket类增加超时和阻塞设置的方法&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setTimeOut&lt;/span&gt;($p_nSendTimeOut &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, $p_nRecvTimeOut &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$nSend &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;int&lt;/span&gt;)$p_nSendTimeOut;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$nRecv &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;int&lt;/span&gt;)$p_nRecvTimeOut;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrSend &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;sec&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; $nSend, &lt;span style="color:#e6db74"&gt;&amp;#39;usec&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;int&lt;/span&gt;)(($p_nSendTimeOut &lt;span style="color:#f92672"&gt;-&lt;/span&gt; $nSend) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;));&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrRecv &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;sec&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; $nRecv, &lt;span style="color:#e6db74"&gt;&amp;#39;usec&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;int&lt;/span&gt;)(($p_nRecvTimeOut &lt;span style="color:#f92672"&gt;-&lt;/span&gt; $nRecv) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;));&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;socket_set_option&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;SOL_SOCKET&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;SO_RCVTIMEO&lt;/span&gt;, $arrSend);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;socket_set_option&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;SOL_SOCKET&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;SO_SNDTIMEO&lt;/span&gt;, $arrRecv);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setBlock&lt;/span&gt;($p_bType &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($p_bType){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;socket_set_block&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;socket_set_nonblock&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;客户端端运行前，先设置一下超时或非阻塞即，此时程序不会再阻塞了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ClientSocket&lt;/span&gt;($strHost, $nPort);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pClient&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;setTimeOut&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$pClient-&amp;gt;setBlock(false);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//do request here&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;同样在服务端设置超时和非阻塞也是可以的，给ServerSocket增加超时和非阻塞设置的方法&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_setNoBlock&lt;/span&gt;($p_pSocket){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;socket_set_nonblock&lt;/span&gt;($p_pSocket);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_setTimeOut&lt;/span&gt;($p_pSocket, $p_nSendTimeOut &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, $p_nRecvTimeOut &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$nSend &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;int&lt;/span&gt;)$p_nSendTimeOut;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$nRecv &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;int&lt;/span&gt;)$p_nRecvTimeOut;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrSend &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;sec&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; $nSend, &lt;span style="color:#e6db74"&gt;&amp;#39;usec&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;int&lt;/span&gt;)(($p_nSendTimeOut &lt;span style="color:#f92672"&gt;-&lt;/span&gt; $nSend) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;));&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrRecv &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;sec&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; $nRecv, &lt;span style="color:#e6db74"&gt;&amp;#39;usec&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;int&lt;/span&gt;)(($p_nRecvTimeOut &lt;span style="color:#f92672"&gt;-&lt;/span&gt; $nRecv) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1000&lt;/span&gt;));&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;socket_set_option&lt;/span&gt;($p_pSocket, &lt;span style="color:#a6e22e"&gt;SOL_SOCKET&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;SO_RCVTIMEO&lt;/span&gt;, $arrSend);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;socket_set_option&lt;/span&gt;($p_pSocket, &lt;span style="color:#a6e22e"&gt;SOL_SOCKET&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;SO_SNDTIMEO&lt;/span&gt;, $arrRecv);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;将SelectServerSocket的socket_accept后产生的连接设置为非阻塞&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;loop&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrRead &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrWrite &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $arrExp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_setNoBlock&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再次运行服务端，客户端也不会阻塞了。&lt;/p&gt;&#10;&lt;p&gt;在while循环里面使用socket_select进行查询，效率比较低下，有先的连接要等下次循环才能处理；有时候并没有连接需要处理，也一直在循环。可以结合前面介绍过的&lt;a class="link" href="https://courages.us/php-%e4%ba%8b%e4%bb%b6%e9%a9%b1%e5%8a%a8%e5%bc%80%e5%8f%91/" target="_blank" rel="noopener"&#10; &gt;PHP Libev扩展&lt;/a&gt;进行监听&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvServerSocket&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServerSocket&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_onConnect&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$pReadClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvIo&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;READ&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; ($watcher, $revents) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_reply&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$pReadWatcher &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvIo&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pSocket&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;READ&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; ($watcher, $revents) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_onConnect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strHost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$nPort &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25003&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strProtocol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvServerSocket&lt;/span&gt;($strHost, $nPort);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;代码看起来简单了很多。当原始套接字监听到可读事件时，便为新的套接字也创建可读事件监听 ，在事件里面处理新的连接。&lt;/p&gt;&#10;&lt;p&gt;通常的服务端程序是一个进程监听原始套接字，然后交由其他进程/线程处理新的连接套接字，与客户端进行交互，提升服务端性能。这样子又涉及到了多进程/多线程的控制、通信，需要一套完善的体系才行。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MulProcessServerSocket&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvServerSocket&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_execute&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_reply&lt;/span&gt;()){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#75715e"&gt;//子进程执行完毕，通知父进程&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;exit&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_onConnect&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$pid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pcntl_fork&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//父进程和子进程都会执行下面代码&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ($pid &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#75715e"&gt;//错误处理：创建子进程失败时返回-1.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;die&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;could not fork&amp;#39;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ($pid) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#75715e"&gt;//父进程会得到子进程号，所以这里是父进程执行的逻辑&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;pcntl_wait&lt;/span&gt;($status); &lt;span style="color:#75715e"&gt;//等待子进程中断，防止子进程成为僵尸进程。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#75715e"&gt;//子进程得到的$pid为0, 所以这里是子进程执行的逻辑。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$pReadClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvIo&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;READ&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; ($watcher, $revents) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_execute&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;还可以使用stream_socket_*系列函数来创建sockt服务端和客户端。类似的创建一个客户端与之前的服务端进行交互&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ClientStreamSocket&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; $pConnetion &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $strAddress &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tcp://127.0.0.1:2016&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $nTimeOut &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $nFlag &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STREAM_CLIENT_CONNECT&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; $strErrorCode &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; $strErrorMsg &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BLOCK&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NOBLOCK&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__construct&lt;/span&gt;($p_strAddress, $p_nTimeOut &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, $p_nFlag &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STREAM_CLIENT_CONNECT&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strAddress&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_strAddress;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nTimeOut&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_nTimeOut;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nFlag&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_nFlag;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pConnetion&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_socket_client&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strAddress&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorCode&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorMsg&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nTimeOut&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nFlag&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pConnetion&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Exception&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;connect exception:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorMsg&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorCode&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pConnetion&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;($p_strMessage){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fwrite&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pConnetion&lt;/span&gt;, $p_strMessage) &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strlen&lt;/span&gt;($p_strMessage))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Exception&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Can not send data&amp;#39;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//接收一行，阻塞至\n结束&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//$strMessage = fgets($this-&amp;gt;pConnetion);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//指定长度读取&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//$strMessage = fread($this-&amp;gt;pConnetion, 1024);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_socket_recvfrom&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pConnetion&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//$strMessage = stream_get_contents($this-&amp;gt;pConnetion);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $strMessage;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fclose&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pConnetion&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pConnetion&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setContext&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setTimeOut&lt;/span&gt;($p_nTimeOut &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_set_timeout&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pConnetion&lt;/span&gt;, $p_nTimeOut);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setBlock&lt;/span&gt;($p_nMode &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ClientStreamSocket&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;BLOCK&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_set_blocking&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pConnetion&lt;/span&gt;, $p_nMode);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__destruct&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pConnetion&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strHost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$nPort &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25003&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strProtocol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$nProtocol = getprotobyname($strProtocol);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strAddress &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $strProtocol&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;://&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;$strHost&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;$nPort;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pStream &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ClientStreamSocket&lt;/span&gt;($strAddress);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$pStream-&amp;gt;setBlock(ClientStreamSocket::NOBLOCK);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$pStream-&amp;gt;setTimeOut(1);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;var_dump&lt;/span&gt;($pStream&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;());&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pStream&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;hello from client&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;var_dump&lt;/span&gt;($pStream&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;());&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pStream&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用stream_socket_*系列函数创建客户端要简单不少&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;首先使用&lt;a class="link" href="http://php.net/manual/zh/function.stream-socket-client.php" target="_blank" rel="noopener"&#10; &gt;stream_socket_client&lt;/a&gt;创建一个socket操作流(stream)&lt;/li&gt;&#10;&lt;li&gt;然后就可以像操作流式文件那样造成socket stream，使用fread和fwrite进行读写操作，也可以使用stream_socket_recvfrom和stream_socket_sendto进行操作&lt;/li&gt;&#10;&lt;li&gt;使用fclose或stream_socket_shutdown关闭连接&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;使用stream_socket_*系列函数创建一个服务端来与之前的客户端进行交互，同样很简单，也与ServerSocket类似&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;php&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServerStreamSocket&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $pServer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $pClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $strAddress &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tcp://127.0.0.1:2016&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; $nFlag &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STREAM_SERVER_LISTEN&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;BLOCK&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;NOBLOCK&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; $strErrorCode &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; $strErrorMsg &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__construct&lt;/span&gt;($p_strAddress, $p_nFlag &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;STREAM_SERVER_LISTEN&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strAddress&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_strAddress;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;nFlag&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $p_nFlag;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_create&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_create&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_socket_server&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strAddress&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorCode&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorMsg&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt; ){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Exception&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;create exception:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorMsg&lt;/span&gt;, $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;strErrorCode&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt; ;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;accept&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_socket_accept&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt; ){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt; ;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;accept&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;echo&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Client&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_socket_get_name&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; is now connected to us. &lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;hello world from server&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_reply&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$mxData &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;var_dump&lt;/span&gt;($mxData);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($mxData &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fclose&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;echo&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;client disconnected.&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Client:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;trim&lt;/span&gt;($mxData)&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;($strMessage);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_reply&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;write&lt;/span&gt;($p_strMessage){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//$nLen = fwrite($this-&amp;gt;pClient, $p_strMessage);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$nLen &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_socket_sendto&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, $p_strMessage);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($nLen &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strlen&lt;/span&gt;($p_strMessage))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Exception&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Can not send data&amp;#39;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//接收一行，阻塞至\n结束&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//$strMessage = fgets($this-&amp;gt;pClient);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//指定长度读取&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//$strMessage = fread($this-&amp;gt;pClient, 1024);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$strMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_socket_recvfrom&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1024&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//$strMessage = stream_get_contents($this-&amp;gt;pClient);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; $strMessage;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fclose&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setContext&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setTimeOut&lt;/span&gt;($p_pConnetction, $p_nTimeOut &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_set_timeout&lt;/span&gt;($p_pConnetction, $p_nTimeOut);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setBlock&lt;/span&gt;($p_pConnetction, $p_nMode &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServerStreamSocket&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;BLOCK&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;stream_set_blocking&lt;/span&gt;($p_pConnetction, $p_nMode);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;__destruct&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;close&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SelectServerStreamSocket&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServerStreamSocket&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;loop&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;loop&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrRead &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrWrite &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $arrExp &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$arrClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;array&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$arrRead &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $arrClient;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;stream_select&lt;/span&gt;($arrRead, $arrWrite, $arrExp, &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;in_array&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt;, $arrRead)){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;$arrClient[] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;$nKey &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;array_search&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt;, $arrRead);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;unset&lt;/span&gt;($arrRead[$nKey]);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;foreach&lt;/span&gt;($arrRead &lt;span style="color:#66d9ef"&gt;as&lt;/span&gt; $pConnetcion){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;$bRes &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_reply&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;($bRes &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;$nKey &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;array_search&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, $arrClient);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;unset&lt;/span&gt;($arrClient[$nKey]);;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//usleep(100);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvServerStreamSocket&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ServerStreamSocket&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_onConnect&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$pReadClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvIo&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;READ&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; ($watcher, $revents) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_reply&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$pReadWatcher &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvIo&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pServer&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;READ&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; ($watcher, $revents) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_onConnect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MulProcessServerStreamSocket&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvServerStreamSocket&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_execute&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt;(&lt;span style="color:#f92672"&gt;!&lt;/span&gt;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_reply&lt;/span&gt;()){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#75715e"&gt;//子进程执行完毕，通知父进程&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;exit&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;protected&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_onConnect&lt;/span&gt;(){&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;$pid &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pcntl_fork&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ($pid &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;die&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;could not fork&amp;#39;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ($pid) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;pcntl_wait&lt;/span&gt;($status);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_connect&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;$pReadClient &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvIo&lt;/span&gt;($this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;pClient&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;READ&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; ($watcher, $revents) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;$this&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_execute&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;Ev&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strHost &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$nPort &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;25003&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strProtocol &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//$nProtocol = getprotobyname($strProtocol);&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$strAddress &lt;span style="color:#f92672"&gt;=&lt;/span&gt; $strProtocol&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;://&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;$strHost&lt;span style="color:#f92672"&gt;.&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;:&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;$nPort;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EvServerStreamSocket&lt;/span&gt;($strAddress);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$pServer&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;run&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里演示客户端与服务端交互，都是两步走，先发送一个请求再获取结果。在Thrift RPC远程调用中，既可先发送请求，过一会儿再来获取结果，达到异步交互的目的；也可发送完请求后立即获取结果，达到同步请求的目的。&lt;/p&gt;&#10;&lt;p&gt;参考链接：&lt;br&gt;&#10;&lt;a class="link" href="http://www.codeproject.com/Tips/418814/Socket-Programming-in-PHP" target="_blank" rel="noopener"&#10; &gt;Socket Programming in PHP&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.binarytides.com/socket-programming-streams-php/" target="_blank" rel="noopener"&#10; &gt;Socket programming with streams in php&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.binarytides.com/php-socket-programming-tutorial/" target="_blank" rel="noopener"&#10; &gt;PHP Socket programming tutorial&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://blog.51yip.com/php/673.html" target="_blank" rel="noopener"&#10; &gt;php 实例说明 socket通信机制&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://www.laruence.com/2010/10/29/1774.html" target="_blank" rel="noopener"&#10; &gt;Mpass – PHP做Socket服务的解决方案&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://serverfault.com/questions/329845/how-to-forcibly-close-a-socket-in-time-wait" target="_blank" rel="noopener"&#10; &gt;How to forcibly close a socket in TIME_WAIT?&lt;/a&gt;&lt;/p&gt;&#10;</description></item></channel></rss>