从一个聊天室Demo研究即时通讯

传输协议 websocket 传输格式 json
具体业务根据json传输的内容来实现。

1.先从最直观的页面入口开始分析

先启动项目

屏幕快照 2017-08-26 下午10.22.36.png

打开页面

屏幕快照 2017-08-26 下午10.24.58.png

打开项目源文件,找到对应的入口文件

屏幕快照 2017-08-26 下午10.28.10.png

分析接口:
连接服务器:

ws://127.0.0.1:7272

登陆:(用户名:222,聊天室ID:1)

{"type":"login","client_name":"222","room_id":"1"}  返回数据:{"type":"login","client_id":xxx,"client_name":"xxx","client_list":"[...]","time":"xxx"}

发送消息:(to_client_id发送给谁,all表示聊天室所有人,content消息内容)

{"type":"say","to_client_id":"all","to_client_name":"","content":"66666"}

接收消息:

{"type":"say","from_client_id":xxx,"to_client_id":"all/client_id","content":"xxx","time":"xxx"}

退出:

{"type":"logout","client_id":xxx,"time":"xxx"}

测试(Advanced REST client):

屏幕快照 2017-08-26 下午10.46.45.png

服务器地址:http://www.chaisz.xyz/webchat
socket接口:ws://www.chaisz.xyz:7272

一切OK,接下来准备研究一下iOS

ios项目地址:https://github.com/chaishuanzhu/xchat-ios

服务端代码

<?php

// set_time_limit(0);

// sleep(5);

// 这里是我们上面得到的deviceToken,直接复制过来(记得去掉空格)
$deviceToken = 'ed8c1c155a6daf448f610ae749eec794be551f8d1b145448711eea973583f820';


// Put your private key's passphrase here:
$passphrase = '123456';


// Put your alert message here:
$message = 'My first push test!';


////////////////////////////////////////////////////////////////////////////////


$ctx = stream_context_create();

stream_context_set_option($ctx, 'ssl', 'allow_self_signed', true);

stream_context_set_option($ctx, 'ssl', 'verify_peer', false);

stream_context_set_option($ctx, 'ssl', 'local_cert', '/Applications/MAMP/htdocs/Push-dev/ck.pem');

stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);


// Open a connection to the APNS server

//这个为正是的发布地址

 // $fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);

//这个是沙盒测试地址,发布到appstore后记得修改哦

 $fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err,$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

//$fp=stream_socket_client("udp://127.0.0.1:1113", $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);

if (!$fp)

exit("Failed to connect: $err $errstr" . PHP_EOL);


echo 'Connected to APNS' . PHP_EOL;


// Create the payload body

$body['aps'] = array(

'alert' => $message,

'sound' => 'default'

);


// Encode the payload as JSON

$payload = json_encode($body);


// Build the binary notification

$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;


// Send it to the server

$result = fwrite($fp, $msg, strlen($msg));


if (!$result)

echo 'Message not delivered' . PHP_EOL;

else

echo 'Message successfully delivered' . PHP_EOL;


// Close the connection to the server

fclose($fp);

?>

ios端代码

#import "AppDelegate.h"
#import <UserNotifications/UserNotifications.h>

@interface AppDelegate ()<UNUserNotificationCenterDelegate>

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    // 注册
    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    [center requestAuthorizationWithOptions:UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionCarPlay completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if (!error) {  
            [[UIApplication sharedApplication]registerForRemoteNotifications];
        }
    }];
    center.delegate = self;
    return YES;
}


- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    // 把此处输出的 “deviceToken” 去掉空格 配置到 php 代码中,就可以向这台设备发送通知了。
    NSLog(@"regisger success:%@", deviceToken);
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(nonnull NSError *)error{
    
    NSLog(@"%@",error);
}

@end

测试结果:

屏幕快照 2017-09-10 下午11.55.33.png

未完待续!

GetWayworker与ThinkPHP结合使用做一个聊天应用后台。

1. 创建项目

在命令行下面,切换到你的web根目录下面并执行下面的命令:

composer create-project topthink/think xchat  --prefer-dist
屏幕快照 2017-09-13 下午11.23.59.png

到应用根目录安装GetWayworker

composer require workerman/gateway-worker
屏幕快照 2017-09-13 下午11.29.24.png

安装GatewayClient

composer require workerman/gatewayclient
屏幕快照 2017-09-13 下午11.32.06.png

然后下载一个聊天室Demo:http://www.workerman.net/workerman-chat

把里面的文件放到应用中。完成后的项目目录如下。

屏幕快照 2017-09-13 下午11.40.32.png
屏幕快照 2017-09-13 下午11.42.01.png

修改start.php

屏幕快照 2017-09-13 下午11.46.16.png

修改Events.php (参考:http://doc2.workerman.net/326107)

屏幕快照 2017-09-13 下午11.47.43.png

启动应用

php start.php start
屏幕快照 2017-09-13 下午11.51.12.png

测试链接:

屏幕快照 2017-09-13 下午11.55.04.png

新建bind.php控制器测试:

<?php
namespace app\index\controller;
//加载GatewayClient。安装GatewayClient参见本页面底部介绍
require_once ROOT_PATH.'vendor/workerman/gatewayclient/Gateway.php';
// GatewayClient 3.0.0版本开始要使用命名空间
use GatewayClient\Gateway;
// 设置GatewayWorker服务的Register服务ip和端口,请根据实际情况改成实际值
class Bind
{

  public function index() {
    echo '66666';
  }
    public function bind () {

        Gateway::$registerAddress = '127.0.0.1:1236';

        // 假设用户已经登录,用户uid和群组id在session中
        $uid      = '123456';
        $group_id = '1';
        $client_id = '7f00000108fe00000001';
        // client_id与uid绑定
        Gateway::bindUid($client_id, $uid);
        // 加入某个群组(可调用多次加入多个群组)
        Gateway::joinGroup($client_id, $group_id);
    }

    public function send_message($uid = '123456', $message = '25652652', $group = '1') {
        // //加载GatewayClient。安装GatewayClient参见本页面底部介绍
        // require_once '/your/path/GatewayClient/Gateway.php';
        // // GatewayClient 3.0.0版本开始要使用命名空间
        // use GatewayClient\Gateway;
        // 设置GatewayWorker服务的Register服务ip和端口,请根据实际情况改成实际值
        Gateway::$registerAddress = '127.0.0.1:1236';

        // 向任意uid的网站页面发送数据
        Gateway::sendToUid($uid, $message);
        // 向任意群组的网站页面发送数据
        Gateway::sendToGroup($group, $message);

        $this -> post('http://www.chaisz.xyz/xchat/index.php/push/push/ios',array('msg' => '54131321'));
    }

    function post($url, $post_data){
          //初始化
          $curl = curl_init();
          //设置抓取的url
          curl_setopt($curl, CURLOPT_URL, $url);
          //设置头文件的信息作为数据流输出
          curl_setopt($curl, CURLOPT_HEADER, 1);
          //设置获取的信息以文件流的形式返回,而不是直接输出。
          curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
          //设置post方式提交
          curl_setopt($curl, CURLOPT_POST, 1);
          //设置post数据
          curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
          //执行命令
          $data = curl_exec($curl);
          //关闭URL请求
          curl_close($curl);
          //显示获得的数据
          // print_r($data);
    }
}

屏幕快照 2017-09-13 下午11.57.41.png

测试:

  1. http://xchat.chaisz.xyz/index/bind/bind 这一步要把用户id和socket连接建立时生成的client_id传到服务器进行绑定。同时根据uid查找用户加入的群组。

    接口地址: http://xchat.chaisz.xyz/index/bind/bind
    返回格式: json
    请求方式: http/https post
    请求参数说明:
    名称 类型 必填 说明
    uid string 用户ID
    client_id string socket连接返回的ID
    返回参数说明:
    名称 类型 说明
    参考JSON返回示例 - -
    参考JSON返回示例 :
    {"code": 200,"message": "success!"}
  2. http://xchat.chaisz.xyz/index/bind/send_message 向用户发送消息

屏幕快照 2017-09-14 上午12.01.02.png
IMG_0208.PNG
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 在此特此声明:一下所有链接均来自互联网,在此记录下我的查阅学习历程,感谢各位原创作者的无私奉献 ! 技术一点一点积...
    远航的移动开发历程阅读 11,076评论 12 197
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 从前有一个叫聪聪的蓝精灵。他很喜欢搞发明。有一天,他跟其他的蓝精灵在一个大树洞里面玩耍。也就是他们的家,他...
    邹秉轩小可爱阅读 618评论 3 3
  • 姓名:叶银芬 公司:宁波慈星股份有限公司 《六项精进》289期学员 反省二组 【知~学习】 《六项精进》大纲...
    Fanny_c554阅读 104评论 0 0