摘要:我們的平臺上有虛擬商品和實體商品兩大分類,當(dāng)時也考慮到了消息的讀取狀態(tài)。商家發(fā)送時間是否已讀。看前端代碼當(dāng)前的所有代碼并不是最終的,目前只是階段性開發(fā),后期在項目中逐步完善。
前段時間公司提了一個新的需求,在商品的詳情頁要實現(xiàn)站內(nèi)買家和商品賣家實時通訊的功能以方便溝通促成交易,要開發(fā)此功能當(dāng)時首先考慮到的就是swoole和workerman了,從網(wǎng)上大概了解了一下關(guān)于這兩款工具的闡述,功能都是相當(dāng)強大的,考慮到項目的進度問題,還是選擇上手容易比較快的GatewayWorker。
先看一下我們前端設(shè)計高大上的模板,分別是用戶和賣家后臺。 功能還是比較全的,幾乎模仿的是QQ。
業(yè)務(wù)上的大概需求是,用戶在進入某個商品詳情頁下,給用戶提供一個和賣家溝通的接口,根據(jù)商品的ID找到對應(yīng)的賣家,類似于淘寶,還有發(fā)送圖片,發(fā)送對應(yīng)的商品鏈接;商戶后臺也差不多。
我們的平臺上有虛擬商品和實體商品兩大分類,當(dāng)時也考慮到了消息的讀取狀態(tài)。我的表最初設(shè)計如下,沒有加任何的索引,考慮的或許也不夠周全,有見地的前輩還望指點一二!
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ā)送消息類型(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ā)送時間", `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è)計好了,接下來就是搭建服務(wù)了,當(dāng)前項目開發(fā)的框架用的是TP5,選擇的Websocket框架是GatewayWorker框架,關(guān)于GatewayWorker與TP5的整合方法可以看我的這篇文章,講到了在Linux和
Windows下的整合安裝。
http://www.cnblogs.com/wt645631686/p/7219519.html
整合好了之后需要根據(jù)當(dāng)前服務(wù)器的一些端口配置在修改一些默認(rèn)的配置,因為需要客戶端通過指定的端口建立連接。
TP5整合好了之后Gateway和workerman的主體目錄結(jié)構(gòu)都在TP5的框架目錄vendor下的workerman目錄下。需要修改里面gateway目錄下的一些文件的端口及IP地址配置。
配置完成之后,進入項目目錄,按照workerman官方手冊提供的使用方法,用命令php start.php start啟動socket服務(wù),如以下截圖,分別是1238和8282端口。當(dāng)然可以在后臺運行,詳細(xì)的使用方法請參考手冊。
啟動好了之后那么就需要在客戶端開始下手了,我們項目里是在前端頁面里用建立的鏈接。看前端代碼
當(dāng)前的所有代碼并不是最終的,目前只是階段性開發(fā),后期在項目中逐步完善。
var ws; // 連接服務(wù)端 function connect() { // 創(chuàng)建websocket ws = new WebSocket("ws://"+document.domain+":8282"); //當(dāng)時為了方便以后的維護,這里在php的全局文件里定義了一個常量來定義ip,后來本地開發(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)閉,定時重連"); connect(); }; ws.onerror = function(e) { console.log(e); console.log("出現(xiàn)錯誤"); }; } // 握手 function onopen() { var joint = "{"type":"handshake","role":"user"}"; ws.send(joint); } // 服務(wù)端發(fā)來消息時 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ā)送失敗,請稍后再試!"); } 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上傳失敗
后臺部分
//微信上傳圖片 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 ) { //客戶端錯誤 return json_encode(["status" => -1]); } if (!is_not_empty_string($toMid)) { //系統(tǒng)錯誤 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ù)器端圖片上傳錯誤 return json_encode(["status" => -2]); } $message = json_encode($data); //Log入庫 $insertId = PmodelPush::addChatLog(self::$uid, $toMid, $message, $message_type, 1, $accIsOnline); if ($insertId === false) { //入庫失敗(服務(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") ]); }
其他一些不是很重要的代碼就不拿出來了。
當(dāng)前項目只是一個簡單的需求,并沒有把GatewayWorker很多強大的功能體現(xiàn)出來,大家以后在項目開發(fā)中遇到更為復(fù)雜的需求,參考官方手冊提供的一些Demo就可以慢慢實現(xiàn)并開發(fā)出更為健壯的項目!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/28151.html
摘要:我們的平臺上有虛擬商品和實體商品兩大分類,當(dāng)時也考慮到了消息的讀取狀態(tài)。商家發(fā)送時間是否已讀。看前端代碼當(dāng)前的所有代碼并不是最終的,目前只是階段性開發(fā),后期在項目中逐步完善。 前段時間公司提了一個新的需求,在商品的詳情頁要實現(xiàn)站內(nèi)買家和商品賣家實時通訊的功能以方便溝通促成交易,要開發(fā)此功能當(dāng)時首先考慮到的就是swoole和workerman了,從網(wǎng)上大概了解了一下關(guān)于這兩款工具的闡述,...
摘要:我們的平臺上有虛擬商品和實體商品兩大分類,當(dāng)時也考慮到了消息的讀取狀態(tài)。商家發(fā)送時間是否已讀。看前端代碼當(dāng)前的所有代碼并不是最終的,目前只是階段性開發(fā),后期在項目中逐步完善。 前段時間公司提了一個新的需求,在商品的詳情頁要實現(xiàn)站內(nèi)買家和商品賣家實時通訊的功能以方便溝通促成交易,要開發(fā)此功能當(dāng)時首先考慮到的就是swoole和workerman了,從網(wǎng)上大概了解了一下關(guān)于這兩款工具的闡述,...
摘要:我們的平臺上有虛擬商品和實體商品兩大分類,當(dāng)時也考慮到了消息的讀取狀態(tài)。商家發(fā)送時間是否已讀。看前端代碼當(dāng)前的所有代碼并不是最終的,目前只是階段性開發(fā),后期在項目中逐步完善。 前段時間公司提了一個新的需求,在商品的詳情頁要實現(xiàn)站內(nèi)買家和商品賣家實時通訊的功能以方便溝通促成交易,要開發(fā)此功能當(dāng)時首先考慮到的就是swoole和workerman了,從網(wǎng)上大概了解了一下關(guān)于這兩款工具的闡述,...
摘要:背景最近在一些項目需要用到實時推送給分組的用戶,前端需要傳輸給后端的信息比較少,通過多方考慮選擇了通過框架基于搭建微服務(wù)。擁有定時器異步客戶端異步異步異步異步消息隊列等眾多高性能組件。配合的定時器,也可以定時推送數(shù)據(jù)。 背景 最近在一些項目需要用到Websocket實時推送給分組的用戶,前端需要傳輸給后端的信息比較少,通過多方考慮選擇了通過GatewayWorker框架(基于Worke...
摘要:即時通訊中,最重要的是響應(yīng)速度,我們需要展示消息列表那么這時會有未讀消息,未讀數(shù)量,最后一條消息內(nèi)容,時間等等。目前設(shè)計是單表單庫。這里只是對即時通訊設(shè)計上做了一些簡要的闡述,如有疑問和建議,請在評論區(qū)回復(fù)。 詳解即時通訊設(shè)計實現(xiàn)(PHP+GatewayWorker+Redis) 需要實現(xiàn)的功能 一對一聊天(私聊) 一對多聊天(群聊) 類似QQ,微信等聊天列表 實時消息 顯示 工具...
閱讀 2567·2023-04-25 17:33
閱讀 648·2021-11-23 09:51
閱讀 2951·2021-07-30 15:32
閱讀 1394·2019-08-29 18:40
閱讀 1939·2019-08-28 18:19
閱讀 1465·2019-08-26 13:48
閱讀 2237·2019-08-23 16:48
閱讀 2275·2019-08-23 15:56