一、关于Swoole
    关于Swoole的一切,包括环境搭建、接口说明、示例等文档,可以访问官方网站 http://www.swoole.com
    所以swoole和php的环境搭建这里就不再啰嗦。
    二、服务架构
    1. 服务架构如下面的结构图:
    基于Swoole实现的即时聊天通讯Socket服务(支持websocket连接) - 图1
    服务端主要有http服务和socket服务,存储方式有mysql(持久化)和文件(或者内存如redis)。http服务主要用来提交要发送的消息存到数据,成功之后才通过socket进行消息推送。http提交信息比较简单也不是要讲的重点,这里也不多说。用户在连接上服务器之后,服务器需要为当前连接与对应用户的映射关系和群组在线用户消息,这些数据可以通过文件或者内存的方式进行缓存。
    1. 连接池,看了swoole的教程我们知道,每个连接都会有一个唯一的id,这里我们称之为fd。由于我们发送消息时不可能每次都带上自个的用户消息,这样会很浪费带宽,所以我们就要将fd作为索引建立连接池,建立当前fd和对用用户id的映射关系,这样我们就可以通过fd快速检索用户信息,这里我们使用swoole table来存储。
    2. 待检池。每个连接都必须在规定时间内通过身份验证才能保持连接,否则连接被关闭。待检池就是用来存储新连接用于检查他们的合法性,检查过程中发现验证通过或者连接超时都从待检池移除,并对超时连接进行关闭。这些数据使用swoole table来存储。
    3. 群组通知池。由于swoole table的局限性(当然可以使用redis,为了简单这里使用文件),该部分数据使用文件进行存储,该目录存储的是每个群组的在线用户,记录的是在线用户的fd,当我们收到该群的消息时,我们就可以通过群id获取在线的连接并广播群消息。
    3. 用户数据。该目录使用用户id为索引缓存用户信息,同时建立用户id和对应连接fd的映射关系,这样我们就可以通过用户id快速检索对应的连接fd来发送数据。 我们知道,在给另外一个用户发消息的时候我们往往只知道对方的用户id,而只知道用户id无法知道将消息推送给哪个socket连接,有了用户id和fd的映射,就可以解决该问题。

    1. 存储文件部分文件结构如下:
      基于Swoole实现的即时聊天通讯Socket服务(支持websocket连接) - 图2

    三、业务流程
    1. 双人聊天业务流程图如下:
    基于Swoole实现的即时聊天通讯Socket服务(支持websocket连接) - 图3
    2. 群聊业务流程图如下:
    基于Swoole实现的即时聊天通讯Socket服务(支持websocket连接) - 图4
    为了同时支持socket和websocket连接,每次连接都先判断连接类型,对于websocket要进行简单的握手。关于websocket的讲解可以看这篇以下文章:websocket协议详解及数据处理实例
    五、消息格式
    客户端消息发送格式如下(注意要加上结束符#$#):
    身份验证

    1 {"infoType": 100001,"connectionType": 2,"data":{"token":"","userId":1}}#$#

    实际应用中token改为实际验证的token
    双人对话

    1 {"infoType": 110001,"connectionType": 2,"data":{"userId":1,"toUserId":2,"messageContent":"user message","messageType":1}}#$#

    群聊消息

    1 {"infoType": 110002,"connectionType": 2,"data":{"userId":1,"clubId":1,"messageContent":"club message","messageType":1}}#$#

    服务端返回消息格式:
    双人对话

    1 {"code":"N00000","message":"xxx","infoType":110001,"data":{"userId":1,"toUserId":2,"messageContent":"user message","messageType":1,"userName":"test1","avatar":""}}#$#

    群聊

    1 {"code":"N00000","message":"xxx","infoType":110002,"data":{"userId":1,"clubId":1,"messageContent":"club message","messageType":1,"userName":"test1","avatar":""}}#$#

    消息主要使用json格式进行传输,传输的内容和格式大家可以自己定义,代码层面做相应修改就好,infoType的含义看项目下的 CommonDefine.php 文件,这里就不多说。

    六、运行
    在安装好swoole和php之后,直接运行项目文件夹下的App.php文件
    php /xxx/application/Projects/IMSocket/App.php -i e
    前台后台运行可以通过SwooleServer.php里面的配置项进行配置,还要注意将公共和项目下的config目录中的配置修改为自己的

    七、测试
    项目目录下有test1.html和test2.html两个文件,分别在两个浏览器中打开,就可以用来简单的测试收发数据了。
    GitHub地址 https://github.com/xiaolingzi/Swoole.IMSocket