免费国产精品自在自线-91精品国产色综合久久久浪潮-99热久久免费频精品-国产精品国模在线观看-久久亚洲国产精品成人?V秋霞-久久国产一级A片免费播放-亚洲国产欧洲综合97久久-久久国产白嫩美女呻吟高潮

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運營的一線實戰(zhàn)洞察。

基于WebSocket的多人實時協(xié)作繪畫平臺設(shè)計與實現(xiàn)

基于WebSocket的多人實時協(xié)作繪畫平臺設(shè)計與實現(xiàn) 簡介在前后端分離架構(gòu)中實時通信是構(gòu)建在線協(xié)作類應(yīng)用的核心技術(shù)。WebSocket作為全雙工長連接協(xié)議憑借低延遲和雙向通信優(yōu)勢已成為白板協(xié)作、共享畫布、在線批注等場景的首選方案。本文從實時通信基礎(chǔ)原理出發(fā)講解如何利用SpringBoot后端與Vue前端搭建多人實時繪畫平臺涵蓋WebSocket連接管理、消息協(xié)議設(shè)計、Canvas矢量筆跡同步、歷史畫布恢復(fù)、斷線重連與心跳?;畹汝P(guān)鍵環(huán)節(jié)。通過實際項目案例展示從開發(fā)到Nginx部署的完整鏈路并總結(jié)常見問題與排查技巧幫助開發(fā)者快速掌握實時協(xié)作類應(yīng)用的工程化實現(xiàn)思路。 多人協(xié)作繪畫最怕什么畫著畫著別人看不到你的筆跡或者說一句話要等半秒才顯示那種體驗基本就廢了。我最近在做一個基于SpringBootVueWebSocket的多人實時在線協(xié)作繪畫平臺今天把整套設(shè)計思路和源碼實現(xiàn)細(xì)節(jié)從頭到尾捋一遍。適合正在做實時交互類項目的同學(xué)參考尤其是前后端分離架構(gòu)下WebSocket的落地場景——用來做協(xié)作白板、共享畫布、在線批注之類的功能完全可以直接抄作業(yè)。這個項目本身不復(fù)雜核心就一句話用WebSocket把多個瀏覽器客戶端的繪畫事件實時同步到服務(wù)端再由服務(wù)端廣播給其他人。但真正寫起來你會發(fā)現(xiàn)連接管理、消息協(xié)議、畫布同步、斷線重連、心跳?;蠲恳粋€節(jié)點都有坑。我會把關(guān)鍵代碼、參數(shù)選擇、踩過的坑全部分享出來。1. 項目需求拆解與技術(shù)選型1.1 核心需求從“單人畫板”到“多人同步畫板”先看需求。單機(jī)版繪畫板很好做無非是Canvas監(jiān)聽鼠標(biāo)事件畫完之后生成base64圖片。但多人協(xié)作意味著兩個核心變化第一每個操作都是消息。畫了一筆不是一個純本地行為而是一次事件廣播。其他用戶收到后在自己的畫布上重放。所以必須有一個穩(wěn)定的實時通信通道。第二狀態(tài)要一致。新加入的人要能看到此前別人畫的所有內(nèi)容否則他打開頁面就是一片空白。因此還需要一個“歷史畫布數(shù)據(jù)”的恢復(fù)機(jī)制比如保存所有筆跡坐標(biāo)或者定期生成快照?;谶@兩點我選型如下能力模塊技術(shù)方案選型理由后端基礎(chǔ)框架SpringBoot 2.7.x生態(tài)成熟WebSocket集成簡單團(tuán)隊上手快前端框架Vue 3 Vite組合式API寫實時交互更清爽Vite開發(fā)調(diào)試體驗好實時通信原生WebSocketSpring WebSocket模塊不引入STOMP是因為本文案場景只有“廣播”一種消息模式原生協(xié)議更輕量定制空間大數(shù)據(jù)庫MySQL存用戶和房間只需要房間維度的元信息不需要存儲全部筆跡降低復(fù)雜度畫布實現(xiàn)HTML5 Canvas 矢量筆跡數(shù)據(jù)直接傳base64圖片帶寬壓力大矢量坐標(biāo)重繪更平滑為什么不用輪詢或SSE輪詢延遲高SSE是單向的無法滿足雙向?qū)崟r通信。WebSocket在低延遲、雙向通信上都有天然優(yōu)勢。如果想深入對比可以看WebSocket是長連接全雙工連接建立后不需要反復(fù)握手對高頻繪畫事件來說這是最合適的協(xié)議。1.2 項目結(jié)構(gòu)前后端分離模塊怎么劃分整個項目我保持了典型的前后端分離結(jié)構(gòu)collaborative-drawing/ ├── backend/ │ ├── src/main/java/com/drawing/ │ │ ├── config/ // WebSocket配置、跨域配置 │ │ ├── controller/ // 房間創(chuàng)建、用戶進(jìn)入等HTTP接口 │ │ ├── model/ // 消息實體、房間實體 │ │ ├── handler/ // WebSocket處理器 │ │ └── service/ // 房間管理服務(wù) │ └── src/main/resources/ └── frontend/ ├── src/ │ ├── api/ // HTTP接口封裝 │ ├── components/ // 畫布組件、顏色選擇器等 │ ├── views/ // 首頁、繪畫頁 │ ├── store/ // Pinia狀態(tài)管理 │ └── utils/ // WebSocket封裝這個結(jié)構(gòu)有幾個好處后端只需要管好“連接”和“轉(zhuǎn)發(fā)”具體的畫布邏輯全部放前端服務(wù)端不關(guān)心你的畫筆是什么顏色、粗度是多少它只負(fù)責(zé)把每個事件原封不動地派發(fā)給房間內(nèi)其他人。這樣職責(zé)邊界非常clear后續(xù)如果要擴(kuò)展聊天、白板標(biāo)注等能力只需要加消息類型。2. 后端實時通信核心實現(xiàn)2.1 加入依賴與WebSocket配置SpringBoot引入WebSocket非常方便先在pom.xml加入依賴dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-websocket/artifactId /dependency然后寫一個配置類注冊WebSocket端點Configuration public class WebSocketConfig implements WebSocketConfigurer { Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(drawingHandler(), /draw) .setAllowedOrigins(*); } Bean public WebSocketHandler drawingHandler() { return new DrawingHandler(); } }這里要注意setAllowedOrigins(*)在開發(fā)環(huán)境確實方便但生產(chǎn)環(huán)境必須顯式指定域名否則會被跨域風(fēng)險和安全掃描盯上。如果前端端口是5173那就寫setAllowedOrigins(http://localhost:5173)。2.2 消息協(xié)議設(shè)計一個JSON搞定所有事件多人協(xié)作繪畫需要同步的事件類型不多但設(shè)計協(xié)議時要有前瞻性。我定義了一個統(tǒng)一的消息模型public class Message { private String type; // 消息類型join, draw, clear, history, pong... private String roomId; // 房間ID private String userId; // 用戶ID private Object data; // 數(shù)據(jù)體可能是筆跡坐標(biāo)、清屏指令等 }前端發(fā)送的消息都是這樣一個結(jié)構(gòu)后端只做校驗和轉(zhuǎn)發(fā)。data字段用Object接收再通過Jackson轉(zhuǎn)成對應(yīng)的對象這樣不同消息類型可以攜帶不同的數(shù)據(jù)體同時又不需要為每種消息寫一堆類。常見的消息類型如下消息類型方向data內(nèi)容join客戶端 → 服務(wù)端房間信息draw客戶端 → 服務(wù)端 → 其他客戶端筆跡點數(shù)組 [{x, y}, ...]clear客戶端 → 服務(wù)端 → 其他客戶端無history服務(wù)端 → 新加入客戶端歷史筆跡數(shù)據(jù)pong客戶端 → 服務(wù)端心跳回復(fù)draw消息中我傳的是“一段筆畫”的數(shù)據(jù)而不是單個點。這樣有幾個好處第一減少消息數(shù)量用戶鼠標(biāo)按下到抬起之間攢一批點一次性發(fā)送網(wǎng)絡(luò)壓力小很多第二接收端可以一次性重繪避免頻繁重繪導(dǎo)致的閃爍。2.3 連接管理與房間廣播核心處理器是DrawingHandler繼承TextWebSocketHandler重寫三個方法Component public class DrawingHandler extends TextWebSocketHandler { // 房間 - 該房間所有會話 private final MapString, ListWebSocketSession roomSessions new ConcurrentHashMap(); Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { // 從URL參數(shù)中拿到roomId比如 ws://localhost:8080/draw?roomroom1userIduser1 String room session.getAttributes().get(roomId).toString(); roomSessions.computeIfAbsent(room, k - new CopyOnWriteArrayList()).add(session); } Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 解析JSON轉(zhuǎn)發(fā)給同房間其他人 } Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { String room session.getAttributes().get(roomId).toString(); ListWebSocketSession sessions roomSessions.get(room); if (sessions ! null) { sessions.remove(session); } } }房間ID我從URL參數(shù)解析在握手?jǐn)r截器中放入session attributes。這樣每個連接進(jìn)來就能知道自己屬于哪個房間不用在消息里反復(fù)攜帶房間ID也方便定向廣播。廣播邏輯簡單粗暴但有效private void broadcastToRoom(String roomId, String userId, String payload) { ListWebSocketSession sessions roomSessions.get(roomId); if (sessions null || sessions.isEmpty()) { return; } for (WebSocketSession s : sessions) { if (s.isOpen() !userId.equals(s.getAttributes().get(userId))) { s.sendMessage(new TextMessage(payload)); } } }這里注意要排除發(fā)送者自己否則前端的處理邏輯會重復(fù)畫兩次。前端自己繪制的筆跡由本地Canvas直接繪制不需要再走一遍網(wǎng)絡(luò)回包。2.4 歷史畫布恢復(fù)新用戶不白屏新用戶加入一個已經(jīng)畫了很多內(nèi)容的房間如果不做任何處理他只能看到之后產(chǎn)生的筆跡。我采用了一個簡單的方案后端內(nèi)存中維護(hù)每個房間的“歷史筆跡列表”用戶加入時一次性推給他。private final MapString, ListObject roomHistory new ConcurrentHashMap(); // 在handleTextMessage中收到draw消息時 ListObject history roomHistory.computeIfAbsent(roomId, k - new ArrayList()); history.add(drawData); // 在afterConnectionEstablished中發(fā)送history消息 session.sendMessage(new TextMessage(historyJson));這個方案適合教學(xué)項目和中小規(guī)模場景內(nèi)存里放一段時間內(nèi)的筆跡數(shù)量大了以后再做滑動窗口比如只保留最近500條。更專業(yè)的做法是存Redis或者直接落庫但那樣IO成本高還需要考慮時序問題反而把項目搞復(fù)雜了。3. 前端繪畫交互與WebSocket集成3.1 Canvas畫筆實現(xiàn)從鼠標(biāo)事件到矢量坐標(biāo)前端我用了Vue 3組合式API Canvas 2D。畫筆邏輯很直接canvas idboard width800 height600/canvasconst canvas ref(null); const ctx ref(null); let drawing false; let currentPoints []; function onMouseDown(e) { drawing true; currentPoints []; const { x, y } getPos(e); ctx.value.beginPath(); ctx.value.moveTo(x, y); currentPoints.push({ x, y }); } function onMouseMove(e) { if (!drawing) return; const { x, y } getPos(e); ctx.value.lineTo(x, y); ctx.value.stroke(); currentPoints.push({ x, y }); } function onMouseUp(e) { if (!drawing) return; drawing false; // 把這一筆的坐標(biāo)數(shù)組發(fā)給服務(wù)端 ws.send(JSON.stringify({ type: draw, roomId: currentRoomId, userId: currentUserId, data: currentPoints })); currentPoints []; }getPos需要計算鼠標(biāo)相對于Canvas左上角的坐標(biāo)不能用e.clientX直接用因為Canvas可能不在視口左上角function getPos(e) { const rect canvas.value.getBoundingClientRect(); return { x: e.clientX - rect.left, y: e.clientY - rect.top }; }這個過程有幾處容易出問題的地方stroke()每次調(diào)用都會從beginPath的位置重畫效率低一點但對實時繪畫影響不大簡單直接最穩(wěn)妥。另外如果用高分辨率屏還需要處理Canvas的縮放比例否則畫出來是模糊的const dpr window.devicePixelRatio || 1; canvas.value.width width * dpr; canvas.value.height height * dpr; canvas.value.style.width width px; canvas.value.style.height height px; ctx.value.scale(dpr, dpr);這塊不處理在Retina屏上畫出來的線條就會發(fā)虛。我當(dāng)時排查了很久才發(fā)現(xiàn)是這個問題。3.2 遠(yuǎn)程筆跡重放收到數(shù)據(jù)怎么畫收到draw消息后前端需要把別人的筆跡畫出來。注意要從對方坐標(biāo)數(shù)組的第一個點開始連接function handleDraw(data) { const points data; if (points.length 0) return; ctx.value.beginPath(); ctx.value.moveTo(points[0].x, points[0].y); for (let i 1; i points.length; i) { ctx.value.lineTo(points[i].x, points[i].y); } ctx.value.stroke(); }有人會問為什么不用lineCap如果默認(rèn)因為Canvas中stroke是整個路徑一次性處理的所以跨多個點的折線會自動連接不會有鋸齒。還有一個細(xì)節(jié)畫筆顏色和粗細(xì)必須跟著消息一起傳。每個人可能選了不同的顏色如果不傳新用戶就會用默認(rèn)顏色畫別人的筆跡。我在draw消息的data里加了一個對象data: { points: currentPoints, color: currentColor, size: currentSize }后端把整個data原樣廣播前端重繪時先設(shè)置strokeStyle和lineWidth再畫路徑。這樣每個人的畫筆狀態(tài)就是獨立的。3.3 WebSocket封裝自動重連與心跳?;钋岸薟ebSocket不能裸寫必須封裝一個帶重連機(jī)制的類。我在utils/ws.js里做了這樣的封裝let socket null; let retryCount 0; let heartBeatTimer null; export function connectWebSocket(roomId, userId, handlers) { const protocol location.protocol https: ? wss : ws; const url ${protocol}://${location.host}/draw?room${roomId}userId${userId}; socket new WebSocket(url); socket.onopen () { retryCount 0; startHeartBeat(); }; socket.onmessage (event) { const msg JSON.parse(event.data); if (msg.type history) { handlers.onHistory(msg.data); } else if (msg.type draw) { handlers.onDraw(msg.data); } else if (msg.type clear) { handlers.onClear(); } }; socket.onclose () { stopHeartBeat(); if (retryCount 5) { retryCount; setTimeout(() connectWebSocket(roomId, userId, handlers), 1000 * retryCount); } }; socket.onerror (err) { console.error(WebSocket error:, err); // 某些情況下error后會自動close所以不用在這里重連 }; } function startHeartBeat() { heartBeatTimer setInterval(() { if (socket.readyState WebSocket.OPEN) { socket.send(JSON.stringify({ type: ping })); } }, 30000); }后端收到ping消息后簡單回一個pong或者直接忽略因為WebSocket協(xié)議本身有心跳機(jī)制但瀏覽器端JS無法直接控制協(xié)議層的心跳報文所以應(yīng)用層心跳是必要的。如果不做心跳連接在一段時間空閑后會被Nginx或云服務(wù)商的網(wǎng)關(guān)斷開。我之前被這個問題坑過一次畫板放著不動幾分鐘再畫就沒反應(yīng)了就是因為連接已被靜默斷開前端還渾然不知。加了心跳之后連接穩(wěn)定性顯著提升。斷線重連的間隔用退避策略第一次1秒第二次2秒最多5次避免短時間頻繁重連打爆服務(wù)端。斷線期間用戶畫的本地筆跡不會丟但無法同步給其他人這一點在UI上可以給個提示“連接已斷開正在重連”我當(dāng)時是加了一個狀態(tài)角標(biāo)。4. 原型系統(tǒng)集成與前后端部署實踐4.1 SpringBoot CORS與WebSocket攔截器細(xì)節(jié)前后端分離后HTTP接口會面臨跨域問題。SpringBoot的處理方式很常規(guī)Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOrigins(http://localhost:5173) .allowedMethods(*); } }但WebSocket的握手請求不受這個CORS配置管控需要在WebSocket握手階段處理。在WebSocketConfig里調(diào)用setAllowedOrigins即可前面已經(jīng)提過。如果是Nginx反代還需要在Nginx配置中允許Upgrade相關(guān)的請求頭這個我們放到后面排查部分說。線程模型方面SpringBoot默認(rèn)內(nèi)嵌Tomcat會對WebSocket連接做阻塞式IO處理Tomcat 8.5以上版本已經(jīng)支持Java WebSocket 1.1的異步處理。我這里沒有做復(fù)雜的并發(fā)控制因為每段筆跡的消息體就幾百字節(jié)單機(jī)幾百個并發(fā)連接完全沒問題。但如果要做集群部署就需要引入消息中間件進(jìn)行跨節(jié)點廣播了這就是另一個層面的架構(gòu)問題了。4.2 前端Vue組件化工具欄、顏色選擇器和畫布分離前端不能把所有邏輯塞在一個頁面里至少要拆成工具欄組件、畫布組件和連接狀態(tài)組件。我的頁面結(jié)構(gòu)如下DrawingBoard.vue ├── ToolBar.vue // 畫筆顏色、粗細(xì)、清除畫布按鈕 └── BoardCanvas.vue // Canvas畫布 鼠標(biāo)事件 重繪邏輯ToolBar中用Pinia來保存當(dāng)前顏色和粗細(xì)BoardCanvas讀取這些狀態(tài)工具欄上“清除”按鈕觸發(fā)一個clear消息前端收到后清空畫布同時后端也清空該房間的歷史筆跡防止別人加入時又看到已清除的內(nèi)容function clearBoard() { ctx.value.clearRect(0, 0, canvas.value.width, canvas.value.height); ws.send(JSON.stringify({ type: clear, roomId: currentRoomId, userId: currentUserId })); }后端收到clear后把對應(yīng)房間的歷史列表清空再向其他人廣播clear。顏色選擇器我用的是input typecolor勝在原生、零依賴。粗細(xì)滑塊用input typerange這兩個配合起來就能滿足基礎(chǔ)繪圖需求。如果想更專業(yè)可以上slider預(yù)設(shè)筆刷但核心邏輯不變。4.3 使用Nginx代理WebSocket的配置示例如果前端構(gòu)建后部署到Nginx后端單獨跑在8080端口那么Nginx配置需要把HTTP請求和WebSocket升級請求都代理到后端。這里給出完整的配置片段server { listen 80; server_name drawing.example.com; # 前端靜態(tài)資源 location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } # 后端HTTP接口 location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # WebSocket升級 location /draw { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header Host $host; proxy_read_timeout 3600s; proxy_send_timeout 3600s; } }關(guān)鍵就是proxy_set_header Upgrade $http_upgrade和Connection upgrade這兩行。沒有它們?yōu)g覽器握手請求會被Nginx當(dāng)作普通HTTP請求處理返回400或504。proxy_read_timeout默認(rèn)60秒如果不改大WebSocket長時間空閑會被Nginx主動斷開心跳可以部分解決但直接把超時調(diào)大更省心。4.4 從開發(fā)到生產(chǎn)Docker部署注意事項我習(xí)慣把后端和前端分別打Docker鏡像用docker-compose一鍵拉起。后端Dockerfile非常簡單FROM maven:3.8-openjdk-11 AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests FROM openjdk:11-jre-slim WORKDIR /app COPY --frombuild /app/target/drawing.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]前端Dockerfile更簡單構(gòu)建完的靜態(tài)文件放到Nginx鏡像里FROM node:18 AS build WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:stable-alpine COPY --frombuild /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80注意前端在構(gòu)建時要配置環(huán)境變量把VITE_WS_BASE指向ws://域名/draw不要寫死localhost。我在connectWebSocket里用location.host來動態(tài)拼接這樣就可以直接適配不同域名不需要改代碼。5. 常見問題與排查技巧實錄5.1 連接建立后立即斷開狀態(tài)碼1006這是我在開發(fā)中遇到最多的問題。前端顯示W(wǎng)ebSocket連接失敗狀態(tài)碼1006表示連接異常關(guān)閉通常不是瀏覽器主動關(guān)閉而是服務(wù)端或代理層把連接斷了。排查步驟先檢查后端日志看握手是否成功afterConnectionEstablished有沒有被調(diào)用。如果沒被調(diào)用檢查端點地址是否匹配客戶端請求的路徑與registry.addHandler中的路徑是否一致。如果后端有權(quán)限攔截或過濾器檢查是否把WebSocket握手請求攔掉了比如Shiro、Spring Security會默認(rèn)攔截所有請求。如果在Nginx后面檢查Upgrade和Connection配置。最后看端口是否被防火墻攔截netstat -an | grep 8080看一下監(jiān)聽狀態(tài)。有一個容易踩的坑在SpringBoot中如果同時引入了spring-boot-starter-securityWebSocket握手會默認(rèn)走認(rèn)證流程導(dǎo)致401。解決方案是在Security配置中放行WebSocket端點http.authorizeRequests() .antMatchers(/draw, /api/**).permitAll() ...或者干脆在WebSocket握手?jǐn)r截器中做自定義認(rèn)證用Token參數(shù)校驗身份。5.2 多人同時畫畫面互相覆蓋或者錯亂這個問題一般不是網(wǎng)絡(luò)問題而是畫筆狀態(tài)沒有隔離。比如用戶A設(shè)置了紅色畫筆他發(fā)的消息里帶了color但用戶B收到后沒有先設(shè)置strokeStyle就直接畫導(dǎo)致紅色畫完后再畫自己的黑色結(jié)果兩個人的筆跡顏色混在一起。解決思路遠(yuǎn)端重繪時每次都重新設(shè)置顏色和粗細(xì)不要依賴上一次的狀態(tài)。同時在draw消息的數(shù)據(jù)體里把color和size放在points旁邊。一次完整的消息結(jié)構(gòu)如下{ type: draw, roomId: room1, userId: user1, data: { points: [{x: 10, y: 20}, {x: 11, y: 22}], color: #ff0000, size: 3 } }5.3 歷史消息推送時機(jī)問題新用戶加入時后端在afterConnectionEstablished里發(fā)送history消息。但有一個并發(fā)問題如果用戶加入的瞬間正好有人正在畫一筆那這一筆可能已經(jīng)寫入歷史列表而前端還沒收到history消息就收到了draw消息導(dǎo)致順序錯亂——先畫了最新一筆然后又被history整個重繪覆蓋最新一筆反而不見了。我的解決辦法是前端收到history后先清空畫布再執(zhí)行歷史重繪在連接建立之后的一小段時間內(nèi)收到的draw消息先緩存起來等history處理完再批量執(zhí)行。也可以更簡單地在后端廣播時加一個序號前端按序號排序但這會增加協(xié)議復(fù)雜度。對Demo項目來說用“緩存后處理”的方式足夠了。let pendingDraws []; socket.onmessage (event) { const msg JSON.parse(event.data); if (msg.type history) { historyLoaded true; clearCanvas(); redrawHistory(msg.data); pendingDraws.forEach(draw handleDraw(draw)); pendingDraws []; } else if (msg.type draw) { if (!historyLoaded) { pendingDraws.push(msg.data); } else { handleDraw(msg.data); } } };5.4 線程安全與內(nèi)存泄漏roomSessions和roomHistory我用了ConcurrentHashMap內(nèi)層的List用了CopyOnWriteArrayList保證并發(fā)修改和遍歷不沖突。但這只是單機(jī)場景。如果連接不關(guān)閉歷史列表會無限增長形成內(nèi)存泄漏。因此我簡單加了一個上限if (history.size() 500) { history.subList(0, history.size() - 500).clear(); }這種方式很粗暴卻能保證內(nèi)存不會無限膨脹。你也可以把歷史數(shù)據(jù)持久化到Redis或數(shù)據(jù)庫每次新用戶加入時從數(shù)據(jù)庫讀取。那個方案會重很多但對團(tuán)隊協(xié)作產(chǎn)品來說更靠譜。5.5 白屏問題一定檢查Canvas寬高設(shè)置很多新手會把Canvas的寬高寫死在HTML標(biāo)簽里比如canvas width800 height600/canvas這在靜態(tài)頁面沒問題但如果Canvas放在一個響應(yīng)式布局中或者在對話框/彈窗里顯示實際顯示尺寸往往會被CSS縮放而內(nèi)部繪圖分辨率和顯示尺寸不匹配畫出來的線會偏移和模糊。最穩(wěn)妥做法是在mounted里通過容器尺寸動態(tài)設(shè)置Canvas的width和height同時處理devicePixelRatio然后監(jiān)聽窗口大小變化重設(shè)尺寸并重繪歷史數(shù)據(jù)。這部分的代碼比較多但在協(xié)作繪畫項目中屬于基本功。5.6 消息體過大導(dǎo)致連接卡死如果鼠標(biāo)快速移動mouseMove事件觸發(fā)頻率會很高。我試過把每個點都實時發(fā)送結(jié)果消息隊列積壓畫布卡成PPT。后來改為“一筆一筆發(fā)”只在鼠標(biāo)抬起時發(fā)送整段筆跡。這樣一個筆畫最多十幾個或幾十個點消息體幾十字節(jié)到幾百字節(jié)完全在可接受范圍。如果要更精細(xì)的實時效果比如看到對方毛筆筆鋒的實時軌跡可以增加定時批量發(fā)送每50ms發(fā)送一次增量點這樣既有實時性又不會太頻繁。我的項目沒有做這么細(xì)因為一筆一畫的方式對普通白板場景已經(jīng)夠了。6. 項目擴(kuò)展與個人經(jīng)驗總結(jié)這個平臺的骨架搭建起來之后后續(xù)擴(kuò)展空間非常大。我整理了幾個可以繼續(xù)深入的方向更多工具類型矩形、圓形、直線、文字輸入等等只需要擴(kuò)展消息類型的data結(jié)構(gòu)。實時在線狀態(tài)通過join和leave消息維護(hù)用戶列表顯示當(dāng)前房間有哪些人。Undo/Redo后端維護(hù)操作棧廣播undo指令接收端回退一筆。筆跡同步優(yōu)化用差分同步算法只發(fā)送變化區(qū)域或者用二進(jìn)制協(xié)議protobuf替代JSON提升大數(shù)據(jù)量場景下的性能。服務(wù)端集群化多個實例間通過Redis Pub/Sub或MQ做消息轉(zhuǎn)發(fā)保證跨實例房間廣播的一致性。根據(jù)我個人幾次做實時協(xié)作項目的體會WebSocket本身并不難難的是消息協(xié)議設(shè)計和異?;謴?fù)機(jī)制。這個項目里我踩得最深的坑有兩個一個是Nginx代理配置缺失導(dǎo)致外網(wǎng)連接不穩(wěn)定另一個是歷史消息和實時消息的順序問題。如果你也打算寫類似功能建議先從這兩個點入手設(shè)計能少走不少彎路——先把一次典型的多人會話流程畫清楚再寫代碼后面會省很多事。本文還有配套的精品資源點擊獲取
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
丁香六月啪| 亚洲国产成人裸舞| 国产AV一区二区三区最新精品| 99热精品9| 嫩草视频观看| 色吧五月婷婷| 亚洲丁香五月天在线视频| 六月丁香网| 激情五月丁香六月婷婷| 五月婷婷狠天天色综合| 丁香六月色婷婷| 玖玖91| 婷婷综合一二三| 这里只有精品99视频| 亚洲一区二区 成人网站戴套| 97干网站| 五月婷婷丁香六月| 丁香美女主播视频在线观看| 99色热视频| 久99热在线观看| 亚洲精品无人区| 天堂综合久| 久久99色色| 九月丁香婷婷综合激情| 狠狠爱综合网| 亚洲天堂爱爱| 久久五月情| 亚洲视频在线观看| 国产3p露脸普通话对白| 丁香五月婷婷啪啪| 99热欧美| www.久久| 亚洲V国产V欧美V久久久久久| 丁香五月网在线观看| 婷婷在线免费| 久久婷婷伊人| 激情小说五月天| 91视频久久久| 欧美性猛交99久久久99| 九九狠狠干| 丁香六月欧美| 亚洲视频无| 久久久天堂国产精品女人| 青草激情综合| 激情婷婷| 91狠狠色丁香婷婷综合久久狠丁香综合久久精品| 色欲久久综合| 黄网免费观看| 青青草五月天| 激情六月婷婷| 99热这里只有精品66| 丁香五月色网| 五月丁香婷婷色| 狠狠99| 久久久久人妻| 伊人久久大香网| 99九九在线精品热动漫| AV中文在线| 日韩久久色| 天天做天天爱天天玩| 九九热在线99| 99在线视频精品| 色婷婷精品视频| 婷婷狠狠干| 夜夜爽天天日| 伊人色综合久久久| 九九视频在线观看| 操老逼综合网| 99精品网址| 9色在线视频精品观看| 免费碰碰视频久| 热99视频精品在线| 日本一级大片| 婷婷五月丁香综合| 婷婷久久免费看| 99A级片| 大香蕉婷婷丁香视频在线| 伊人久久大香线蕉av一区| 五月丁香六月综合基地| 99色区| www.五月激情.com| 激情内射p| 青青草原福利在线| 激情四射网| 色色五月天婷婷| 五月丁香999| 五月婷六月综合在线观看| 色婷婷XXXXX| 九九热这里只有精品7| 性爱先锋AV| 涩涩五月天综合| 六月丁香婷| WWW夜夜| 停停色综合伊人| 国产精品色一哟哟| 91九色在线视频| 色噜噜狠狠色综合成人网| 欧美丁香婷婷五月| 无码人妻丰满熟妇奶水区码| 五月丁香久久| 免费操超碰| 婷婷五月大香蕉| 色激情综合狠狠婷婷| 五五月五月| 五月综合色播播丁香婷婷| 五月色影院| 新激情五月天天在线网| 成人做爰高潮A片免费视频| 91九九| 婷婷视频在线| 天天日天天做天天舔| 亚洲性爱99在线| 国产偷人妻精品一区| 色色五月天丁香| 五月丁香激情啪啪| 大香蕉娱乐| Av九九| 丁香久久五月天视频在线观看 | 亚洲成av人影院| 97久久婷婷色| 少妇人妻偷人精品无码视频新浪 | 五月丁香啪啪伦理电影| 午夜大香蕉| 影音先锋男人站,影音先锋男人色资源网,影音先锋AV最新资源站,影音先锋AV资源 | 色综合色色| 99,色| 五月天成人伊人| 79色色免费| 综合另类视频| 国产精品岛国片在线观看免费| 淫视馆aV二区一区| 五月婷精品| 乱女乱妇熟女熟妇综合网站| 手机旧版看人妻1025| 99操视频| 狠狠爱综合| 亚洲性色XXXXX| 日韩无码色色| 六六久久黄色| 99视频精品8 | 99热久久这里只有精品| 婷婷色中文| 色 丁香婷婷| 五月婷婷激情久久| 丁香婷婷性久久| 操逼福利视频| 777精品久无码人妻蜜桃| 黄色一级影片| 丁香婷婷激情六月五月开心| 亚洲天堂无码| 久9免费视频| 综久久久| 五月婷综合| 五月天丁香婷婷网| 九月丁香婷婷综合激情| 99热99精品| 激情五月天视频| 人人插9| 五月丁六月婷| 91操人视频| 婷婷五月天Av| 影音先锋一区| 国产熟女大叫受不了| 亚洲色色色色| 亚洲第一av| 五月深爱网| 久久九网| 色噜噜狠噜噜视频| 天天操无码| 91色逼| 九九精品热播| 九月丁香婷婷| 国产丁香五月天婷婷| 天天天天操| 99热热九九| 婷婷五月天伊人| 婷婷偷拍网| 日韩欧美四五区| 色五月激情| 五月婷婷新网站| 午夜一区| 日本在线噜噜| 五月天丁香综合在线| 婷婷激情六月视频| 丁香五月婷婷狠狠色| 人人操五月天| 五月婷AV| www.henhenl| 丁香五月电影| 激情久久五月网| av网站不卡在线| 天天干天天爽天天操| 丁香六月天婷婷| 噜噜狠狠色综无码久久合欧美| 亚洲另类毛片| 天天操比比| 婷婷五月天Av| 久久免费丁香| 欧美成人精品A片免费一区99| 就爱操www com| 人碰人人人玩91| 欧美婷婷成人| 天天日日人| 国产婷伊人| 天天干天天操天天拍| 91婷婷伊人牛牛| 这里只有精品1| 色五月婷婷激情五月| 丁香婷婷五月综合| eeuus五月婷| 超极99精品| 播播网色播播| 精品99网站| 超碰五月婷婷五月天| 99色五月| 天天色天天舔天天爱天天爽| 婷婷激情九月| 色八戒操婷婷| 久9视频| 色欲五月婷婷| 草操AV在线| 啪啪视频99| 美日韩成人| 色婷婷九月综合| 亚洲4区国产欧美| 色五月AV| 五月婷婷在线视频| 好好干av| 五月丁香 六月婷婷a| 六月丁香婷婷爱| 综合色图区| 五月婷婷伊人久久| 久久精品爱爱| 色天堂在线| 国产黄大片在线观看画质优化| 色色色com| 国产五月丁香在线| 色99在线视频| 99思思| 深爱五月亚洲| 桃色Av色哟哟| 大香蕉伊人99| 毛v一区二区视频| 欧洲第一无人区观看| 丁香 亚洲 久久| 欧美成人网婷婷综合在线| 激情综合在线观看| 伊人九九热| 99干日日干| 中文AV网站| 丁香五月婷婷五月天| 亚洲激情五月婷婷日日| 激情综合五月激情17| 97色视频网| 五月综合久久| 色色五月丁香| 丁香五月天激情综合| 天天操天天操天天操天天操天天操天天操天天操天天操天天操 | av五月丁香| 国产FREESEXVIDEOS性中国| 2020日日干| 操熟女成人网| 五月婷婷自拍视频| 激情小说之五月| 26uuu欧美日韩| 五月丁香花视频| 色五月在线综合| 欧亚成人A片一区二区| 欧美 日韩 成人在线| 五月丁香中文| 99色热视频在线| 影音先锋偷偷色男人站| 97婷婷丁香五月综合| 中文字幕丰满孑伦无码专区| 亚洲日韩乱码一区二区三区四区| 五月天成人综合| 91成人视频| 色天五月天在线观看视频| 这里只有精品视频一区| 国产裸舞表演WWWW| 日本五月天婷婷丁香| 天天舔天天摸天天透| 丁香亚洲婷婷五月| 久99久热只有精品国产99| 伊人五月天男人的天堂在线| 日本色婷婷久久99精品91| 久热婷婷| 77799热| 思思久久99热| 99热在这里只有免费精品| 久久亚洲A| 亚洲综合字幕色色| 东北婷婷五月天| 色 五月俺去也| 综合久久丁香婷婷,五月婷婷六月丁香,开心激情综合网,六月丁香在线观看,婷婷丁 | 久久人妻超碰一区| 91精品视频男人的天堂| 色欲婷婷五月天丁香| 《丁香激情综合久久伊人久久》影视在线观看 -高清预告手机免费播放 -三妹影院 | 九色成人AV在线| 67久久| 碰超亚洲| 九九色影院| 丁香五月激情综合婷综| 99惹在线精品免费观看| 国精产品一区一区三区免费视频| 丁香五月天激情免费在线观看AV777| 婷婷射图| ..真实国产乱子伦毛片| 色欲天天综合| 99综合激情久久精品久久| 九九亚洲无码| 99久久国产宗和精品1上映| 成人丁香婷婷| 久久老码第一| 99人人操人人爱久久久| 99久久户外勾搭| 天天做天天爱天天玩| 5月婷婷综合| 日本玖玖在线| 五月天丁香网| 久久天天| 激情黄色小说五月天| 秋霞日本免费毛片A片| 人妻久久久久久| 99综合色| 六月丁香深深爱| 国产超碰人人| 蜜臀综合久草| 色婷婷丁香五月天| 9|无码久久久久久| 婷婷深爱五月| 九九这里精品| 99在线精品视频观看免费下载| 久久婷婷五月综合色和| 开心五月婷婷激情| 亚洲精品国产成人AV在线| 激情5月天天天| 日本在线视频www色| 五月婷婷丁香91| 九九色图| enecarbon-materials.com污K127封锁请涟系@wip1688 | 九九视频精品视频精品| 九九久久五月天综合伊人| 97操碰人免费| 粉嫩AV久久一区二区三区| 五月婷婷视频在线观看| 亚洲人人操BD| 亚洲狠狠婷婷综合久久久| 五月天伊人综合| 亚洲av电影网站| 丁香婷婷啪啪| 精品久久99码| 五月婷婷中文字幕| 99免费视频| 婷婷五月天免费| 他改变了拜占庭| 九九综舍久久| 色婷婷亚洲在线观看| 热91久| 亚洲综合五月天| 碰97久久| 99色在线观看视频| 5五月综合网亚洲| 五月丁香婷中文| 五月天激日本色情在线| 精品五月视频婷婷在线观看| 婷婷五月天堂| 久久婷婷国产| WWW.婷婷五月天.COM| 91精品视频男人的天堂| 中文字幕在线人妻| www.99操| 大香蕉伊然在亚洲90| 亚洲成人在线在线| 色色欧美色色色| 成人精品在线| 女人高潮内射99精品| 99热这里只有精品2| 久久精品夜色噜噜亚洲a∨| 五月婷婷六月丁香激情| 99热这里只有精品22| 色狠狠图片| 四色 爱 婷婷 精品 亚洲 五月天| 永久的网站AAAA | 综合网色| 伊人91| 久久九区| 五月天天天综合| 五月婷久久| 99热这里只有精品1025| 一区二区三区视频| 六月丁香婷婷五月天| 女同激情久久av久久| 六月丁香婷婷色狠狠久久| 日本三级片片| 欧美日韩国产一区| 日本三级大片| 日韩人妻无码一区二区| 五月丁香六月婷婷色| 五月丁香激情综合网官网| 久久精品国产色| 久久久er热| 丁香六月色情| 亚洲第一精品成人999久久精品| 99色在线观看视频| 天天透天天爱| 9 1超碰九色| 超碰99热| 国产精品a无线| 国产午夜伦鲁鲁| 色婷婷很很丝袜| 久久久潮喷-久久久九九-成人AV| 亚洲成片在线观看| 超碰亚洲天堂| 狠狠狠狠狠狠狠狠草| 婷婷日日天天| 九九这里有精品| 97人凄人人操人人爽| 91丨九色丨东北熟女| 久久98| 色综合久久之分久久| 日韩啪啪视品| 五月 成人 婷婷| www.色五月| 视频免费精品免费精品免费精品免费精品免费精品免费精品免费99 | 色九区| 久热这里只有精品在线观看 | 99网址在线看| 九九综合精品| 六月丁香VA| 久操福利| 无码激情AAAAA片-区区| 7777精品伊人久久久大香线蕉最新版| 丁香婷婷五月天激情四射| 九九热10| www.99视频| 91久久综合亚洲鲁鲁五月天| 日韩精品AV一区二区三区| 婷婷五月天丁香综合网| 色婷婷av在线| 婷婷激情五月天亚洲综合| 色播五月| 激情五月综合| 综合玖玖偷拍| 激情婷婷内射| 六月丁香婷婷综合在线| 午夜丁香| 天久久久久| 丁香五月在线视频| 激情网五月| 激情婷婷六月天| 色婷婷狠狠禁久久| 色五月丁香六月资源站| 五月开心深爱激情网| 九九综合九九| 日韩久久日| 97人人干| 丁香五月色激情| 五月激情啪啪啪| 另类激情五月| 色综合久久久久| 亚洲精品一二三| 国产成人综合在线| 婷婷五月天香蕉| 丁香色五月天| 香蕉伊人综合| 天天操夜夜玩!| 丁香婷婷性久久| 亚洲精品又粗又大又爽A片| 久碰综合| 五月婷婷丁香av| 五月婷婷色色色| 五月丁香久久激情综合| 影音先锋女人av鲁色资源网小说免费| 天天做天天爱天天玩| 亚洲综合五月天婷婷丁香| 伊人五月婷婷国产视频| 婷婷日日天天| 99热精品在线| 婷婷的久久网站| 热久视频| 日曰躁夜夜躁2026| 婷婷激情五月天7| 99精品免费| 91肏肏肏| 99丁香五月婷| 色噜噜婷婷| 色爱综合五月| 天天夜夜六月丁香五月婷婷老师| 欧美色五月| 色V狠狠的干| 五月天婷婷无码| 欧美色男人网站| 日本a片网址| 色吧婷婷| 丁香五月婷婷99| 五月激情综合深爱| 日韩一级一片内射视频4K| 欧美精品999| 五月天婷婷乱论小说| 超碰只有精品在线| 亚洲另类AV| 日本熟女三区| 99热只有| 激情综合网五月在线播放| 七七九色| 久久伦乱| 丁香婷婷激情| 亚洲成人另类| 99狠狠| 五月叮香啪| 五月婷婷基地| 4399在线观看免费高清毛片| 日日夜夜噜噜爽爽| av中文字幕免费观看| 秋霞午夜理论| 日本久久网| 亚洲热手机在线观看| 2017狠狠干| 99re热久久| 日产精品久久久久久久蜜臀| 思思热99er在线视频| 婷婷五月色| 丁香五月电影| 五月丁香婷婷基地| 狠狠色噜噜狠狠色噜噜噜999| 色情五月综合婷婷| 三级三久久线久久99久目本WW| 超碰在线中文字幕| 女操碰| 午夜九九九九九九九九九九九九九| 《丁香激情综合久久伊人久久》影视在线观看 -高清预告手机免费播放 -三妹影院 | 中文字幕有多少字| 亚洲色vA| 久久精品日| 激情综合网五月激情| 色婷婷色和| 婷婷五月色天| 色偷偷色婷婷| 91啪啪视频| 97人人射| 亚洲日韩一页精品发布| 天天日天天操天天干| 九九色网专区| 一级黄色尤物综合视频手机在线观看| 久久sp免费视频| 天天插天天射| 综合五月婷婷| 国产乱妇无乱码大黄AA片| 婷婷婷五月天最新综合你懂的| 人妻丰满精品一区二区A片 | 97资源碰碰在线| 丁香伊人网| 亚洲精品视频在线| 99成人| 六月婷色六月| www色综合亚洲92| 超碰99热精品| 六月99天天婷婷激情综合| 激情五月天色播| 精品成人无码A片观看香草视频| 成人AV播放| 99精品色| 婷婷丁香久久| 91人人人人人| 国产成人亚洲综合A∨婷婷| 色情婷婷。| 99热这里只有精品4| 五月丁香激情婷婷综合字幕| 91啦丨九色丨刺激中文| 67194成I人在线观看线路1| 99热免费网站| 色婷小说| 大香蕉婷婷丁香天堂AV| 五月丁香综合啪啪対白| 九九人人看| 丁香五月五月婷婷| 这里只精品热在线18| 91精品又长又大又粗又爽又猛| 超碰成人电影| 一级A片天天操夜夜操| 国内久久久精品99| 91精品综合久久久久久五月丁香| 欧美色五月天| 99色色热热| 9视频在线成人网站| 五月激情综合网| 天天爱天天日| 伊人五月天97| 777影视理论片大全在线观看| 另类视屏| 亚洲日本韩国| 色99日韩| 99热777| 久久婷婷五月丁香网| 中文中文在线| 嫩草视频在线观看| 久久五月婷天天干| 操操碰| 成人精品免费在线观看| 99久久6| 六月婷婷久久大全| 丁香六月婷婷久久综合八月| 婷婷色六月| 九九无码| 色久女| 视色综合| 激情丁香五月婷| 在线超碰91| 无码成人AAAAA毛片AI换脸| 色爽九九| 婷婷五月伦理网站| 五月婷婷六月丁香综合视频在线| 182TV大香蕉| 日本欧美成人片AAAA| 99热这里| 这里只有精品在线视频在线观看| 狠狠做五月婷婷| 欧美综合五月丁香六月婷| 久久免费少妇高潮99精品| 五月婷婷激情久久| 色婷婷先锋| 欧美日韩AAA| 九九热免费观看视频| 五月丁香六月成人| 五月天色色色色色| 日本性视频| 六月丁香网| 丁香六月婷婷综合激情欧美| 99热九九热| 色五月婷婷大| 天天综合色丁香| 婷婷人人操| 五月婷九九草| 无码髙清| 五月天六月婷| 婷婷五月天激情视频| 99视频这里只有免费精品| 日韩日比视频| 成人丁香五月婷| 欧美久久九九| 色情终和网| 天天做天天爱天天高潮| 九九视频这里只有精品| 4399在线日本A片| 丁香五月婷婷在线| 久久精品视频在这里有| 五月婷婷自拍视频| 婷婷丁香五月噜噜噜| 激情婷婷五月天伊人在线观看| 9久精品视频| 97日在线视频| 在线99色| 偷拍九九五月丁香婷婷| 色99视| 五月丁香 狠狠爱| 五月丁香久久久| 久久视频在线视频| 国精产品一区一区三区免费视频 | 久久性爱视频网站| 天天操天天操天天操天天操天天操天天操天天操天天操天天操 | 99热在线精品播放| 国产操B视频| 97欧美在线| 丁乡久久| 日本99在线| 欧美色色色色色色| 91精品婷婷国产综合| 免费AV在线| 午夜婷婷久久| 亚洲操精品| 中美日韩成人在线| 久操大香蕉| 91狠狠综合久久久| 五月天激情综合网站| 九九热这里有精品视频| 99色免费观看全部| 五月丁香色欲| txt五月激情四射网综合俺也来了 五月天婷婷丁香人人操91 | 色五婷婷| 色99网站| 九九人人精品| 日本一级一级一级一级| 国产亚洲99久久精品| 五月丁香狠狠爱| 全部老头和老太XXXXX| 99久久精品免费精品国产_国产精品久久久久久_国产在线|日韩_久久国产精品电影 | 在线观看视频1区| 伊人激情网| 9热在线观看| 9l视频自拍九色9l视频自拍九色9l社区| 九九色人| 草操AV在线| 人妻久久久久久久久| 亚洲狠狠操| 五月丁六月香| 爽极品色| 少妇大叫太大太粗太爽了A片 | 色婷婷影音| 97影院一级片| 国产阿姨日皮艹逼内射视频 | 婷婷五月丁香综合人妻| 深爱激情五月天| 久久精品99| 免费无码毛片一区二区A片| 婷色天堂| 国产色视频网站2| 日本精品99网站| 怡红院99| 天天做天天爱天天要| 色婷婷超碰| 久热9| 天天综合网~91| 久久人人九| 久久综合婷婷激情| 成人免费在线电影| 婷婷激情综合无月| 天天干 夜夜爽| www激情| 中文字幕1区2区。| 99啪99| 精品国产人人爱人人| 日日爱699| 日本精品99| 草了bav视频在线观看| 色婷婷AⅤ| 九九热这里有精品视频| 亭亭五月天成人| 色婷视频| 丁香五月婷婷老师网站| 久久婷婷精品| 色久五月天| 天天操天天操天天操天天操天天操天天操天天操天天操天天操 | 天干干夜夜操| 99热这里只有精品8| 丁香五月综合| 激情骚五月| 丁香无五月网| 99色综合| 午夜不卡久久精品无码免费| 99热99精品| 激情五月婷婷综合网| 99自拍网| yw.av| 丁香六月天婷婷在线| 欧美Va日本Va| 亚洲精品又粗又大又爽A片 | 96精品久久久久久久久| 国产高清RV综合aVa| 色婷操逼| 91干99| 色七色九九| 色婷久| A片天天| 天天天久久久| 久久综合影院 | 婷婷亚洲欧美丁香五月| 99热成人| 色婷婷婷婷| 激情综合激情五月一起草| 丁香六月婷婷| 色琪琪一综合久久激情五月视频| 亚洲激情网站| 成人午夜视频精品一区| 色婷婷久久综合| 日本色狠狠| 1024国产在线| 青青操avbb| 大香蕉婷婷色| 99人妻碰碰碰久久久久| 五月丁香六月婷婷久久久综合| 五月丁香婷婷成人网| 婷婷色片| 欧美色爱五月天| 国产精产国品一二三在观看| 五月丁香六月激情综合网| 99热99美国在线观看| 婷婷五月激情小说| 五月丁花色综合网| 亚洲激情综合| 亚洲sesesese| 91色色色18| 伊人热婷婷| 婷婷五月天另类网站| 黑人糟蹋人妻HD中文字幕| 色九九综合| 五月综合激情| 黑人熟妇一区二区三区| 熟女激情五月天| 99久99久| 区区欧美你爱| 色欧美色色色| 五月丁香色五月| 天天干一干| 五月丁香网视频| 婷婷中文在线| 九九九九综合| 五月丁香啪啪啪综合网| 极品色丁香| 婷婷五月天亚洲五码| 人人干人人操外国| 丁香五月婷婷色情综合| 91亚洲视频| 96五月丁香熟女| 五月天婷婷成人网| 中文字幕高清av| 男人的天堂五月丁香| 久久九九热re6这里有精品| 六月丁香五月激情网| 成人综合网站| 婷婷激情鹿城五月天| 久草热久草在线视频| 久久激情综合| 国产精品久久久久久妇女6080| 26uuu色噜噜精品一区| 色婷视频| 伍月激情天| 校花娇喘呻吟校长陈若雪视频| 激情伊人六| 国产乱子轮XXX农村| 亚洲XX日本| 2050人人操免费工开爱 | 日本色色图| 色色色图| se色99| 精品香蕉99久久久久网站| 五月婷综合性中心| 天天日日| 99成人在线观看| 操九色| 99欧美| 五月色亭丁香| 操老逼综合网| 成人丁香五月天| 激情綜合網址| 91丨九色丨东北熟女| 五月花综合网| 小香蕉av| 五月天狠狠网| 生活片五区| 99热这里有精品| 内射激情在线| 69人人操人人爽| 色婷婷综合影院| 99综合网| 91在线就要啪| 综合激情视频| 在线视频你懂得| 色激情五月天| 五月婷婷人妻| 久久九九玖玖| 色色激情| www.成人婷婷综合| 人人综合久| 久碰视频| 激情小说视频图片| 夜夜 操无码| 无码人妻AV久久久一区二区三区 | 丁香五月婷婷激情网| 色综久久久| 五月色亭丁香| 一区二区成人电影| 色综合五月在线| 69精品人人人人人人| 亚洲第一第二网站| 激情小说之五月| 婷婷在线视频| 六月丁香婷婷六月激情综合| 天堂成人久久| AV大香蕉| 26uuu| 九九热亚洲中文在线观看免费| 91操人人操| 九九99香蕉在线视频播放| 九九国产精视频| 北条麻妃伊人| 日本久久天堂| 婷婷丁香激情五月天色色| 五月天婷婷基地综合网| 亚洲无AV在线中文字幕| 人人草人人爱| 免费色色色| 五月伊人婷婷999| 天天爽天天操| AV性爱在线| 欧日韩AV| 亚洲AV无码成人精品区电影网| 天天狠狠夜夜狠狠2023| 久久久久思思热| 六月丁香花婷婷| 波多野结衣成人作品在线| 婷婷深爱五月| 亚洲精品国产精品乱码视99| 激情五月深爱五月| 丁香五月婷婷99| 久久精品国产一区二区三区四区| 五月花婷婷| 午夜精品777| 9999三级片| 人五月天婷婷喷水| 99色热| 特级西西4444www无码| 久久精品在线| 五月色婷婷中文字幕| 中文不卡av| 在线99热| 久操福利| 精品久久66| 久久激情综合| 狠狠久久婷五月| 丁香六月亚洲| 日本熟妇乱妇熟色A片蜜桃| 丁香五月婷婷啪| 亚洲色情网站| 五月天堂婷婷| 久久综合九九| 99热插| 亚洲丁香婷婷| 免费无码毛片一区二区A片| 99日本黄站| 橾逼网| 99精品无码网站| 久久色五月天| 国产日韩精品SUV| 91超级碰在线视频| 五月天婷婷爱| 激情五月六月丁香| 夜夜骑日日操| www色色com| 精品亚洲国产成AV人片传媒| www91色网站| 五月开心播播网| 天天综合色| 亚洲啪视频| 五月天婷婷小说| 五月天五月天成人网亭亭成人色网站| 天天爽—爽| 婷婷综合在线| 六月丁香大香蕉| www.综合久久| 色yeye欧美| 91狼友视频网页更新| 成人精品视频99在线观看免费| 婷婷婷婷婷婷婷五月丁香| 香蕉操亚洲| 五月婷婷六月情| 久久五月天激情| 色爱终和网| 色五月激情基地| 夜夜噜夜夜奇| 五月丁香少妇A| 五月天色狠狠| 99re思思热在线视频| 国产精品成人在线| av在线观看免费| 啪啪综合| 99热综合在线| 久久久久8888| www.99精品在线| 97人妻碰碰碰久久| 亚洲精品网址| 亚洲xx网| 五月婷婷婷综合网| 色婷婷a v| 五月婷婷天堂| 激情久久久久久| 日韩啪| 超碰chaompinm| 色狠狠色| 久久er免费视频| 五月激情四射婷婷丁香 | 九九一区| 激情五月综合网丁| 91狼友视频在线观看| 依人大香蕉在钱1| 精品五月花| 日韩婷久| 久久999久久999久久999久久| 91chinese 在线| 久久综合丁香| 综合玖玖性爱免费视频| 五月天天天综合| 狠狠操天天操综合| 丁香五月亚洲综合| 丁香 婷婷 亚洲 熟女| 色色网站免费| 丁香五月在线播放| 激情五月婷| 狠狠色婷婷| 97干在线| 男同91| 日本色五月| 夜夜资源站| 日本三级日本三级99| 色色99| 婷婷五月天无码熟女| 五月丁香久久激情网| 五月激情久久综合网| 亚洲中文乱字字幕在线永久| www.久久爱.com| 综合色播| 日韩黄在免| 亚洲AV永久无码影院黑人| 色欲影香| 色情综合网| 日日干日日s| 亚洲视频伍月婷婷| 99在线免费视频| 五月丁香色色网| 激情五月婷婷老师| www.99精品视频| 91丨九色丨东北熟女| 国产丁香五月天婷婷| 精品五月天| 日本久久综合| 嫩BBB搡BBBB榛BBBB| 涩涩激情五月婷婷| 碰碰女| 午夜 外网 精品 在线| 六月丁香社区| 91精品婷婷国产综合久久| 五月丁香色综合| 天堂网亚洲色图| 97操在线视频| 天天操天天谢| 另类 在线| www.色婷婷.com| 色婷综合| 99热福利| 色噜噜狠狠狠综合曰曰曰| 超碰男人色| 激情又色又爽又黄的A片| 久青草大香蕉| 丁香五月激情天AV无码| 色永久| 日本99热| 狠狠色噜噜狠狠狠狠狠色综合久久| 日韩成人电影在线播放| www.爱操com.| 日韩在线观看亚洲| 被男人添B超爽视频| 色噜噜五月丁香婷婷| 亭亭丁香久久五月| 五月丁香六月在线| 爱射综合| 激情亭亭五月| ji'qing'luan'ren'lun| 综合啪啪| 99人妻碰碰久久久禁片| 超碰人人操人人干| 六六久久黄色| 婷婷综合欧美| 欧美xx激情视频在线观看| 五月天婷婷影院| 男人天堂AV在线一区二区| 好吊操这里只有精品| 激情五月丁香婷婷| 在线理论片| 人妻AV在线观看| 五月天精品综合| 九九热视频在线观看| 欧美婷婷丁香五月| 五月天成人在线精品| 激情六月丁香| 色色97丁香婷婷五月天| 狠色狠色狠狠色综合网| 色婷婷丁香五月| 婷婷五月丁香激情| 秋霞电影一级黄| 五月天久久网站| 黄色网址五月婷婷| 五月激情四射婷婷丁香| 五月天婷婷AV| 天堂美国久久| 婷婷伊人无码| 99操逼视频| 欧美日韩日韩成人| 色婷婷伦理| 色综合色色色| 大香蕉伊人爱在线| 丁香六月色婷婷综合| 伊人综合网站| 婷婷五月天激情网| 激情 婷婷| 九九Y精品热播| 色狠狠六月| 99色色网| 久久五月网| 色五月播五月| 五月激情婷婷偷拍| 人妻在线中文字幕久久| 人人操AV| 精品婷婷| 影音先锋91| 在线成人av播放| 亚洲小视频| 色色色色欧美| 精品国产va久| 五月丁香激情综合| 色婷丁香| 五月婷婷天堂| 激情五月综合久久| 99热这里只有精品2| 婷婷五月天国产传媒| 色色亚洲无码| 五月天色婷婷综合| 粉嫩av懂色av蜜臀av熟妇| 99爱视频| 9久9久| 欧美婷婷成人| 丁香五夜激情四射夜夜夜| 婷婷综合六月| 久久九网| 俺去也在线www色官网| 成人做爰A片免费看网站找不到了| 国产精品久久99| 婷婷五月丁香基地| 精品久热| 五月丁香人妻| 婷婷综合在线| 99久久极情精品一区| 操一区| 激情欧美五月丁香| 色综合色| 精品乱码久久久久| 丁香六月婷婷激情综合| 亚洲操B| 五月婷婷色播视频| 丁香五月天视频| 天天日日人| AV中文在线| 丁香五月婷婷姐| 日本人妻伦在线中文字幕| site:jszngf.com| 国产精产国品一二三在观看| 日韩精品999| 五月婷婷草| 狼人婷婷综合| 97人人操| 欧美色色色色色| 色五月在线观看| 噜一噜免费视频| 五月丁香啪| 亚洲XX日本| 五月婷婷伊| 婷婷五月情天| 欧美WW在线网| 亚洲婷婷丁香| 欧美久热| 另类视频在线| 五月天激情中文字幕| 人人摸人人干| 综合网五月| 亚洲AV网站在线观看| 99自拍视频| 激情五月图| 影音先锋高清无码资源网| www一区二区三区| 六月综合婷婷开心伊人| 激情久久久久久久久久久| 欧美99热| 久久思思热| 久久久五月婷婷| 激情婷婷综合网| 99热爱爱干干日| 激情五月天在线观看色婷婷| 国产暴力强伦轩1区二区小说| 亚洲性色XXXXX| 日韩性爱无码| 伦乱天堂| 婷婷五月欧美综合| 丁香影院五月综合| 九九热精品99| 五月色情婷婷| 男人的天堂婷婷色五月| 亚洲激情五月天| 五月天婷婷av| 亚洲精品无AMM毛片| 自拍盗摄 另类| 丁香九月综合| 疯狂做受XXXX高潮A片| 2025年最新亚洲在线欧美| www.射伊蕉婷婷| 成人精品在线| 79色色| 另类A片| www久视频com| 天天综合色| 婷婷色五月激情| 人操91在线| 九九色逼| 俺去也在线视频| 超碰在线观看9| 亚洲精品一区中文字幕乱码| 色五月婷婷影院| 色婷婷综合网| 香蕉曰比| 五月丁香综合激情| 丁香五月婷婷乱| 超碰男人色| 少妇性BBB搡BBB爽爽爽视頻| 可以看的av网站| 丁香婷婷综合激情五月色,开心五月丁香花综合网,激情综合五月亚洲婷婷,五月天 | 五月婷婷啪| 天天插天天插天天操| 97超级碰人人| 91狠狠综合久久| 五月花亭亭| 亚洲中文字幕av| 丁香五月婷婷啪啪视频| 99操久久| 99性爱精品| 99er6免费视频热播| 亚洲殴洲精品Av在线| 五月叮香啪| 夜夜夜夜夜操| 激情深愛五月視頻| 五月婷婷导航| 中文字幕乱码亚洲精品一区| 97性视频| 丁香婷婷色五月合集| 天天爽人人综合免费7799| 激情精品久久| 中文字幕在线免费观看视频| 色五月综合在线| 婷五月丁香| 亚洲视频五区| 天天操天天插天天射| 免费黄色片子| 五月天激情综合| 插插五月天| 26uuu青青| 久久图色4| 97干干干丁香| 九九热免费| 激情综合激情综合| 99aese| 日日爱678| 日本色色网站| 99在线视频。| 久久99综合| 婷婷五月天黄色| 5月丁香啪啪啪| 深爱激情五月天色婷婷| 日韩欧洲亚洲| 99九九热视频免费| 老师的粉嫩小又紧水又多A片视频| 天天搡日日搡aaaaⅩ| 五月天网站亭亭| 久热这里只有精品99re,久热这里只有精品7 | 超碰碰碰碰| 99日本黄站| 久久精品性爱| 婷婷五月综合视频| 婷婷色五月天第7色| 中文字幕综合网| 色婷婷文字幕| 26uuu成人网| 国产乱子轮XXX农村| 亚洲激情网| 国产精品久久..4399| 五月激情婷婷国产精品久久久久久| 玖久精品视频9| 狠狠色性| 激情涩涩网|