成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

使用Websocket框架之GatewayWorker開(kāi)發(fā)電商平臺(tái)買(mǎi)家與賣(mài)家實(shí)時(shí)通訊

Baoyuan / 3369人閱讀

摘要:我們的平臺(tái)上有虛擬商品和實(shí)體商品兩大分類(lèi),當(dāng)時(shí)也考慮到了消息的讀取狀態(tài)。商家發(fā)送時(shí)間是否已讀。看前端代碼當(dāng)前的所有代碼并不是最終的,目前只是階段性開(kāi)發(fā),后期在項(xiàng)目中逐步完善。

前段時(shí)間公司提了一個(gè)新的需求,在商品的詳情頁(yè)要實(shí)現(xiàn)站內(nèi)買(mǎi)家和商品賣(mài)家實(shí)時(shí)通訊的功能以方便溝通促成交易,要開(kāi)發(fā)此功能當(dāng)時(shí)首先考慮到的就是swoole和workerman了,從網(wǎng)上大概了解了一下關(guān)于這兩款工具的闡述,功能都是相當(dāng)強(qiáng)大的,考慮到項(xiàng)目的進(jìn)度問(wèn)題,還是選擇上手容易比較快的GatewayWorker。

先看一下我們前端設(shè)計(jì)高大上的模板,分別是用戶和賣(mài)家后臺(tái)。 功能還是比較全的,幾乎模仿的是QQ。


業(yè)務(wù)上的大概需求是,用戶在進(jìn)入某個(gè)商品詳情頁(yè)下,給用戶提供一個(gè)和賣(mài)家溝通的接口,根據(jù)商品的ID找到對(duì)應(yīng)的賣(mài)家,類(lèi)似于淘寶,還有發(fā)送圖片,發(fā)送對(duì)應(yīng)的商品鏈接;商戶后臺(tái)也差不多。

我們的平臺(tái)上有虛擬商品和實(shí)體商品兩大分類(lèi),當(dāng)時(shí)也考慮到了消息的讀取狀態(tài)。我的表最初設(shè)計(jì)如下,沒(méi)有加任何的索引,考慮的或許也不夠周全,有見(jiàn)地的前輩還望指點(diǎn)一二!

DROP TABLE IF EXISTS `hp_chat_log`;
CREATE TABLE `hp_chat_log` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT "聊天記錄表主鍵id",
  `user_id` int(10) unsigned NOT NULL DEFAULT "0" COMMENT "用戶id",
  `merchant_id` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT "" COMMENT "商家id",
  `send_message` text COLLATE utf8_unicode_ci NOT NULL,
  `send_message_type` tinyint(1) NOT NULL DEFAULT "1" COMMENT "發(fā)送消息類(lèi)型(1:普通文本;2:商品鏈接,3:用戶發(fā)送圖片)",
  `sender` tinyint(1) NOT NULL DEFAULT "1" COMMENT "發(fā)送方。1:用戶。2:商家",
  `send_time` int(11) NOT NULL DEFAULT "0" COMMENT "發(fā)送時(shí)間",
  `read_status` tinyint(1) unsigned NOT NULL DEFAULT "0" COMMENT "是否已讀。0:未讀取。1:已讀取",
  `acc_isonline` tinyint(1) NOT NULL DEFAULT "0" COMMENT "接收方是否在線 (0:不在線;1:在線)",
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=157 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

模板有了,表設(shè)計(jì)好了,接下來(lái)就是搭建服務(wù)了,當(dāng)前項(xiàng)目開(kāi)發(fā)的框架用的是TP5,選擇的Websocket框架是GatewayWorker框架,關(guān)于GatewayWorker與TP5的整合方法可以看我的這篇文章,講到了在Linux和

Windows下的整合安裝。

http://www.cnblogs.com/wt645631686/p/7219519.html

整合好了之后需要根據(jù)當(dāng)前服務(wù)器的一些端口配置在修改一些默認(rèn)的配置,因?yàn)樾枰蛻舳送ㄟ^(guò)指定的端口建立連接。

TP5整合好了之后Gateway和workerman的主體目錄結(jié)構(gòu)都在TP5的框架目錄vendor下的workerman目錄下。需要修改里面gateway目錄下的一些文件的端口及IP地址配置。

配置完成之后,進(jìn)入項(xiàng)目目錄,按照workerman官方手冊(cè)提供的使用方法,用命令php start.php start啟動(dòng)socket服務(wù),如以下截圖,分別是1238和8282端口。當(dāng)然可以在后臺(tái)運(yùn)行,詳細(xì)的使用方法請(qǐng)參考手冊(cè)。

啟動(dòng)好了之后那么就需要在客戶端開(kāi)始下手了,我們項(xiàng)目里是在前端頁(yè)面里用建立的鏈接。看前端代碼

當(dāng)前的所有代碼并不是最終的,目前只是階段性開(kāi)發(fā),后期在項(xiàng)目中逐步完善。

var ws;
    // 連接服務(wù)端
    function connect() {
       // 創(chuàng)建websocket
       ws = new WebSocket("ws://"+document.domain+":8282");  //當(dāng)時(shí)為了方便以后的維護(hù),這里在php的全局文件里定義了一個(gè)常量來(lái)定義ip,后來(lái)本地開(kāi)發(fā)完提交到linux服務(wù)器環(huán)境之后發(fā)現(xiàn)鏈接失??!
       console.log(ws);
       ws.onopen = onopen;
       ws.onmessage = onmessage;
       ws.onclose = function(e) {
        console.log(e);
          console.log("連接關(guān)閉,定時(shí)重連");
          connect();
       };
       ws.onerror = function(e) {
        console.log(e);
          console.log("出現(xiàn)錯(cuò)誤");
       };
    }
     // 握手
    function onopen()
    {
        var joint = "{"type":"handshake","role":"user"}";
        ws.send(joint);
    }
    // 服務(wù)端發(fā)來(lái)消息時(shí)
    function onmessage(e)
    {
        var data = JSON.parse(e.data);
          console.log(data);
        switch(data["type"]){
            // 服務(wù)端ping客戶端
            case "ping":
                ws.send("{"type":"pong"}");
                break;
            // 登錄 更新用戶列表
            case "handshake":
                bindUid(data.client_id);
                $("#client_id").val(data.client_id);
                break;
            // 提醒
            case "reception":
                //{"type":"say","from_client_id":xxx,"to_client_id":"all/client_id","content":"xxx","time":"xxx"}
                warn(data["content"], data["time"], data["timestamp"]);
                break;
        }
    }

    //綁定uid
    function bindUid (client_id) {
        var bindUrl = "{:url("push/push/BindUserClientId")}";
        $.post(bindUrl, {client_id: client_id}, function(data){
            console.log(data);
        }, "json");
    }

    //發(fā)送連接
    function sendLink () {
       sendTrigger("link");
    }
    // 發(fā)送信息
    function sendMessage (){
        sendTrigger("message");
    }
    function sendTrigger(sendType) {
      var toMid     = $("#toMid").val();
      var pid       = $("#pid").val();
      var message   = $("footer .send_content").val();
      var client_id = $("#client_id").val();
      var sendUrl   = "{:url("push/push/SendMessageToMerchant")}";
      $.ajax({
        url:sendUrl,
        type:"POST",
        data:{message:message,toMid:toMid,pid:pid,client_id:client_id,sendType:sendType},
        async:false,
        dataType:"JSON",
        success:function(data){
            data = JSON.parse(data);
            if (data.status < 0) {
                alert("發(fā)送失敗,請(qǐng)稍后再試!");
            } else {
                $("#send_timestamp").val(data.timeStamp);
                $("#send_timestr").val(data.timeStr);
                if (sendType == "link") {
                    $("#main").append(data.html);
                }
            }
        }
      })
    }

    // 提醒
    function warn(content, time, prevTmestamp){
        var V_image = $("#V_image").val();
        var str = "
" + timestampWarn(prevTmestamp, time) + "
" // $("#main").append(str); // } var t = 0; var i = 0, length = images.localId.length; images.serverId = []; /* upload 方法 -------- start */ function upload() { wx.uploadImage( { localId: images.localId[i], success: function (res) { i++; images.serverId.push(res.serverId); if (i < length) { upload(); } var str = "
                                                   
" $("#main").append(str); if(i >= length ) uploadImageToDb(images.serverId); }, fail: function (res){ } }); } /* upload 方法 -------- end */ upload(); } }) }); function uploadImageToDb(images){ var str = ""; var upUrl = "http://xxxxxx.com/push/push/uploadImgage"; var toMid = $("#toMid").val(); var client_id = $("#client_id").val(); $.post(upUrl,{images:images,toMid:toMid,client_id:client_id},function(data){ if(data == 1){ for(var n = 0 ; n < $(".chat-sender").length ; n++){ str = $(".chat-sender").eq(n).attr("serverId")+","; for(var z=0;z上傳失敗
"); } } } } }) } /* 退款選擇圖片 -------- end */

后臺(tái)部分

//微信上傳圖片
    public function uploadImgageAction () {
        if (!Request::instance()->isPost()) { notFund(); }
        $images    = $_POST["images"];
        if (empty($images)) die;
        $toMid     = input("post.toMid", "" , "string");
        $client_id = input("post.client_id", "", "string");
        if (strlen($client_id) != 20 ) {                                            //客戶端錯(cuò)誤
            return json_encode(["status" => -1]);
        }
        if (!is_not_empty_string($toMid)) {                                         //系統(tǒng)錯(cuò)誤
            return json_encode(["status" => -2]);
        }

        require_once dirname(dirname(__FILE__)) . "/Events.php";
 
        $accIsOnline    = Gateway::isUidOnline($toMid) == 1 ? 1 : 0;                //判讀商家是否在線
        $message_type   = 3;
        //微信上傳圖片處理Start
        $res = json_decode(file_get_contents("access_token.json"));
        foreach ($res as $key => $value) {
            if($key == "access_token"){
                $access_token = $value;
            }
        }
        $data = [];
        foreach ($images as $k => $v) {
            $str = date("YmdHis").rand(1000,9999).".jpg";
            $targetName = "./upload/chat/".$str;
            if (!file_exists("./upload/chat/")) {
              mkdir("./upload/chat/", 0777, true);
            }
            $ch = curl_init("http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=".$access_token."&media_id=".$v);
            $fp = fopen($targetName, "wb");
            curl_setopt($ch, CURLOPT_FILE, $fp);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            $msg["status"] = curl_exec($ch);
            $msg["filename"] = $str;
            curl_close($ch);
            fclose($fp);
            $data[] = $targetName;
        }
        //微信上傳圖片處理End
        if (!is_not_empty_array($data)) {                                       //微信服務(wù)器端圖片上傳錯(cuò)誤
            return json_encode(["status" => -2]); 
        }
        $message = json_encode($data);
        //Log入庫(kù)
        $insertId       = PmodelPush::addChatLog(self::$uid, $toMid, $message, $message_type, 1, $accIsOnline);
        if ($insertId === false) {                                                  //入庫(kù)失?。ǚ?wù)器故障)
            return json_encode(["status" => -3]);
        }
        $Worker = new Events;
        $message_json   = "{"type":"send","source":"U_" . self::$uid . "","toClientUid":"" . $toMid . "","content":" . $message .",
                "c_type": " . $message_type .", "Db_id":" . $insertId . "}";
        $Worker::onMessage($client_id, $message_json);
        //成功返回相關(guān)數(shù)據(jù)
        return json_encode([
            "status"    => 1,
            "timeStamp" => time(),
            "timeStr"   => date("H:i:s")
        ]);

    }

其他一些不是很重要的代碼就不拿出來(lái)了。

當(dāng)前項(xiàng)目只是一個(gè)簡(jiǎn)單的需求,并沒(méi)有把GatewayWorker很多強(qiáng)大的功能體現(xiàn)出來(lái),大家以后在項(xiàng)目開(kāi)發(fā)中遇到更為復(fù)雜的需求,參考官方手冊(cè)提供的一些Demo就可以慢慢實(shí)現(xiàn)并開(kāi)發(fā)出更為健壯的項(xiàng)目!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/113052.html

相關(guān)文章

  • 使用Websocket框架GatewayWorker開(kāi)發(fā)電商平臺(tái)買(mǎi)家賣(mài)家實(shí)時(shí)通訊

    摘要:我們的平臺(tái)上有虛擬商品和實(shí)體商品兩大分類(lèi),當(dāng)時(shí)也考慮到了消息的讀取狀態(tài)。商家發(fā)送時(shí)間是否已讀??辞岸舜a當(dāng)前的所有代碼并不是最終的,目前只是階段性開(kāi)發(fā),后期在項(xiàng)目中逐步完善。 前段時(shí)間公司提了一個(gè)新的需求,在商品的詳情頁(yè)要實(shí)現(xiàn)站內(nèi)買(mǎi)家和商品賣(mài)家實(shí)時(shí)通訊的功能以方便溝通促成交易,要開(kāi)發(fā)此功能當(dāng)時(shí)首先考慮到的就是swoole和workerman了,從網(wǎng)上大概了解了一下關(guān)于這兩款工具的闡述,...

    ZweiZhao 評(píng)論0 收藏0
  • 使用Websocket框架GatewayWorker開(kāi)發(fā)電商平臺(tái)買(mǎi)家賣(mài)家實(shí)時(shí)通訊

    摘要:我們的平臺(tái)上有虛擬商品和實(shí)體商品兩大分類(lèi),當(dāng)時(shí)也考慮到了消息的讀取狀態(tài)。商家發(fā)送時(shí)間是否已讀??辞岸舜a當(dāng)前的所有代碼并不是最終的,目前只是階段性開(kāi)發(fā),后期在項(xiàng)目中逐步完善。 前段時(shí)間公司提了一個(gè)新的需求,在商品的詳情頁(yè)要實(shí)現(xiàn)站內(nèi)買(mǎi)家和商品賣(mài)家實(shí)時(shí)通訊的功能以方便溝通促成交易,要開(kāi)發(fā)此功能當(dāng)時(shí)首先考慮到的就是swoole和workerman了,從網(wǎng)上大概了解了一下關(guān)于這兩款工具的闡述,...

    CloudDeveloper 評(píng)論0 收藏0
  • 使用Websocket框架GatewayWorker開(kāi)發(fā)電商平臺(tái)買(mǎi)家賣(mài)家實(shí)時(shí)通訊

    摘要:我們的平臺(tái)上有虛擬商品和實(shí)體商品兩大分類(lèi),當(dāng)時(shí)也考慮到了消息的讀取狀態(tài)。商家發(fā)送時(shí)間是否已讀??辞岸舜a當(dāng)前的所有代碼并不是最終的,目前只是階段性開(kāi)發(fā),后期在項(xiàng)目中逐步完善。 前段時(shí)間公司提了一個(gè)新的需求,在商品的詳情頁(yè)要實(shí)現(xiàn)站內(nèi)買(mǎi)家和商品賣(mài)家實(shí)時(shí)通訊的功能以方便溝通促成交易,要開(kāi)發(fā)此功能當(dāng)時(shí)首先考慮到的就是swoole和workerman了,從網(wǎng)上大概了解了一下關(guān)于這兩款工具的闡述,...

    姘存按 評(píng)論0 收藏0
  • 通過(guò)GatewayWorker/Workerman搭建Websocket微服務(wù)

    摘要:背景最近在一些項(xiàng)目需要用到實(shí)時(shí)推送給分組的用戶,前端需要傳輸給后端的信息比較少,通過(guò)多方考慮選擇了通過(guò)框架基于搭建微服務(wù)。擁有定時(shí)器異步客戶端異步異步異步異步消息隊(duì)列等眾多高性能組件。配合的定時(shí)器,也可以定時(shí)推送數(shù)據(jù)。 背景 最近在一些項(xiàng)目需要用到Websocket實(shí)時(shí)推送給分組的用戶,前端需要傳輸給后端的信息比較少,通過(guò)多方考慮選擇了通過(guò)GatewayWorker框架(基于Worke...

    QLQ 評(píng)論0 收藏0
  • PHP即時(shí)通訊設(shè)計(jì)實(shí)現(xiàn)

    摘要:即時(shí)通訊中,最重要的是響應(yīng)速度,我們需要展示消息列表那么這時(shí)會(huì)有未讀消息,未讀數(shù)量,最后一條消息內(nèi)容,時(shí)間等等。目前設(shè)計(jì)是單表單庫(kù)。這里只是對(duì)即時(shí)通訊設(shè)計(jì)上做了一些簡(jiǎn)要的闡述,如有疑問(wèn)和建議,請(qǐng)?jiān)谠u(píng)論區(qū)回復(fù)。 詳解即時(shí)通訊設(shè)計(jì)實(shí)現(xiàn)(PHP+GatewayWorker+Redis) 需要實(shí)現(xiàn)的功能 一對(duì)一聊天(私聊) 一對(duì)多聊天(群聊) 類(lèi)似QQ,微信等聊天列表 實(shí)時(shí)消息 顯示 工具...

    asoren 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<