国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

WebSocket(三) -- 使用websocket+stomp實(shí)現(xiàn)群聊功能

這篇具有很好參考價(jià)值的文章主要介紹了WebSocket(三) -- 使用websocket+stomp實(shí)現(xiàn)群聊功能。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1. 前言:

SpringBoot+websocket的實(shí)現(xiàn)其實(shí)不難,你可以使用原生的實(shí)現(xiàn),也就是websocket本身的OnOpen、OnClosed等等這樣的注解來(lái)實(shí)現(xiàn),以及對(duì)WebSocketHandler的實(shí)現(xiàn),類似于netty的那種使用方式,而且原生的還提供了對(duì)websocket的監(jiān)聽(tīng),服務(wù)端能更好的控制及統(tǒng)計(jì)(即上文實(shí)現(xiàn)的方式)。

但是,真實(shí)項(xiàng)目中還是使用Stomp實(shí)現(xiàn)的居多,因?yàn)楠?dú)立服務(wù)更方便,便于后期搭建集群環(huán)境做橫向擴(kuò)展,且內(nèi)置的方法也很簡(jiǎn)單,既然如此,我們還是以主流實(shí)現(xiàn)方式為準(zhǔn)來(lái)學(xué)習(xí)吧。

2. stomp

當(dāng)直接使用WebSocket時(shí)(或SockJS)就很類似于使用TCP套接字來(lái)編寫Web應(yīng)用。因?yàn)闆](méi)有高層級(jí)的線路協(xié)議(wire protocol),因此就需要我們定義應(yīng)用之間所發(fā)送消息的語(yǔ)義,還需要確保連接的兩端都能遵循這些語(yǔ)義。

就像HTTP在TCP套接字之上添加了請(qǐng)求-響應(yīng)模型層一樣,STOMP在WebSocket之上提供了一個(gè)基于幀的線路格式(frame-based wire format)層,用來(lái)定義消息的語(yǔ)義。

與HTTP請(qǐng)求和響應(yīng)類似,STOMP幀由命令、一個(gè)或多個(gè)頭信息以及負(fù)載所組成。例如,如下就是發(fā)送數(shù)據(jù)的一個(gè)STOMP幀:

>>> SEND
transaction:tx-0
destination:/app/marco
content-length:20

{"message":"Marco!"}

3. 需求:

  1. 登陸:
    WebSocket(三) -- 使用websocket+stomp實(shí)現(xiàn)群聊功能

  2. 1號(hào)用戶加入,發(fā)送消息:
    WebSocket(三) -- 使用websocket+stomp實(shí)現(xiàn)群聊功能

  3. 2號(hào):
    WebSocket(三) -- 使用websocket+stomp實(shí)現(xiàn)群聊功能

  4. 3號(hào):
    WebSocket(三) -- 使用websocket+stomp實(shí)現(xiàn)群聊功能

  5. 退出:
    WebSocket(三) -- 使用websocket+stomp實(shí)現(xiàn)群聊功能

  6. 要求使用stomp完成

4. websocket配置:

// websocket核心配置類
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    /**
     * 注冊(cè)stomp端點(diǎn)
     * @param registry stomp端點(diǎn)注冊(cè)對(duì)象
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 配置stomp端點(diǎn)地址
        registry.addEndpoint("/ws").withSockJS();
    }

    /**
     * 配置消息代理
     * @param registry 消息代理注冊(cè)對(duì)象
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 定義客戶端訪問(wèn)服務(wù)端消息接口時(shí)的前綴
        registry.setApplicationDestinationPrefixes("/app");

        // 配置服務(wù)端推送消息給客戶端的代理路徑
        registry.enableSimpleBroker("/topic");

        // 定義點(diǎn)對(duì)點(diǎn)推送時(shí)的前綴為/queue
        registry.setUserDestinationPrefix("/queue");


        //   Use this for enabling a Full featured broker like RabbitMQ
        /*
        registry.enableStompBrokerRelay("/topic")
                .setRelayHost("localhost")
                .setRelayPort(61613)
                .setClientLogin("guest")
                .setClientPasscode("guest");
        */
    }
}

其中:

  1. @EnableWebSocketMessageBroker:用于開(kāi)啟stomp協(xié)議,這樣就能支持@MessageMapping注解,類似于@requestMapping一樣,同時(shí)前端可以使用Stomp客戶端進(jìn)行通訊;
  2. WebSocketMessageBrokerConfigurer接口:實(shí)現(xiàn)了其中的兩個(gè)方法:
    1. registerStompEndpoints實(shí)現(xiàn):
      1. 注冊(cè)一個(gè)websocket端點(diǎn),客戶端將使用它連接到我們的websocket服務(wù)器。
      2. withSockJS()是用來(lái)為不支持websocket的瀏覽器啟用后備選項(xiàng),使用了SockJS。
      3. 方法名中的STOMP是來(lái)自Spring框架STOMP實(shí)現(xiàn)。 STOMP代表簡(jiǎn)單文本導(dǎo)向的消息傳遞協(xié)議。它是一種消息傳遞協(xié)議,用于定義數(shù)據(jù)交換的格式和規(guī)則。為啥我們需要這個(gè)東西?因?yàn)閃ebSocket只是一種通信協(xié)議。它沒(méi)有定義諸如以下內(nèi)容:如何僅向訂閱特定主題的用戶發(fā)送消息,或者如何向特定用戶發(fā)送消息。我們需要STOMP來(lái)實(shí)現(xiàn)這些功能
    2. configureMessageBroker實(shí)現(xiàn):主要用來(lái)設(shè)置客戶端訂閱消息的路徑(可以多個(gè))、點(diǎn)對(duì)點(diǎn)訂閱路徑前綴的設(shè)置、訪問(wèn)服務(wù)端@MessageMapping接口的前綴路徑、心跳設(shè)置等;
      1. 第一行定義了以“/app”開(kāi)頭的消息應(yīng)該路由到消息處理方法(之后會(huì)定義這個(gè)方法)。
      2. 第二行定義了以“/topic”開(kāi)頭的消息應(yīng)該路由到消息代理。消息代理向訂閱特定主題的所有連接客戶端廣播消息

5. model對(duì)象:

public class ChatMessage {
    private MessageType type;
    private String content;
    private String sender;

    public enum MessageType {
        CHAT,
        JOIN,
        LEAVE
    }

    public MessageType getType() {
        return type;
    }

    public void setType(MessageType type) {
        this.type = type;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getSender() {
        return sender;
    }

    public void setSender(String sender) {
        this.sender = sender;
    }

    @Override
    public String toString() {
        return "ChatMessage{" +
                "type=" + type +
                ", content='" + content + '\'' +
                ", sender='" + sender + '\'' +
                '}';
    }
}

6. controller接收和發(fā)送消息:

/**
 * 發(fā)送廣播消息
 * -- 說(shuō)明:
 *       1)、@MessageMapping注解對(duì)應(yīng)客戶端的stomp.send('url');
 *       2)、用法一:要么配合@SendTo("轉(zhuǎn)發(fā)的訂閱路徑"),去掉messagingTemplate,同時(shí)return msg來(lái)使用,return msg會(huì)去找@SendTo注解的路徑;
 *       3)、用法二:要么設(shè)置成void,使用messagingTemplate來(lái)控制轉(zhuǎn)發(fā)的訂閱路徑,且不能return msg
 */
@Controller
@Slf4j
public class ChatController {

    // 實(shí)現(xiàn)向?yàn)g覽器發(fā)送消息的功能
    private final SimpMessagingTemplate messagingTemplate;

    public ChatController(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    // 用法一:
    @MessageMapping("/send")
    public void sendAll(@RequestParam String msg) {

        log.info("[發(fā)送消息]>>>> msg: {}", msg);

        // 發(fā)送消息給客戶端
        // 第一個(gè)參數(shù)是瀏覽器中訂閱消息的地址,第二個(gè)參數(shù)是消息本身
        messagingTemplate.convertAndSend("/topic/public", msg);
    }

    @MessageMapping("/chat.sendMessage")
    @SendTo("/topic/public")
    public ChatMessage sendMessage(@Payload ChatMessage chatMessage) {
        return chatMessage;
    }

    // 用法二:
    @MessageMapping("/chat.addUser")
    @SendTo("/topic/public")
    public ChatMessage addUser(@Payload ChatMessage chatMessage,
                               SimpMessageHeaderAccessor headerAccessor) {
        // Add username in web socket session
        headerAccessor.getSessionAttributes().put("username", chatMessage.getSender());
        return chatMessage;
    }
}
  1. 消息接口使用@MessageMapping注解,前面講的配置類@EnableWebSocketMessageBroker注解開(kāi)啟后才能使用這個(gè)
  2. 我們在websocket配置中,以/app開(kāi)頭的客戶端發(fā)送的所有消息都將路由到這些使用@MessageMapping注釋的消息處理方法。
    例如,具有目標(biāo)/app/chat.sendMessage的消息將路由到sendMessage()方法,并且具有目標(biāo)/app/chat.addUser的消息將路由到addUser()方法
  3. 這里稍微提一下,真正線上項(xiàng)目都是把websocket服務(wù)做成單獨(dú)的網(wǎng)關(guān)形式,提供rest接口給其他服務(wù)調(diào)用,達(dá)到共用的目的,本項(xiàng)目因?yàn)椴簧婕叭魏螖?shù)據(jù)庫(kù)交互,所以直接用@MessageMapping注解,后續(xù)完整IM項(xiàng)目接入具體業(yè)務(wù)后會(huì)做一個(gè)獨(dú)立的websocket服務(wù)
  4. 發(fā)送消息的兩個(gè)用法:
    1. 用法一:要么配合@SendTo(“轉(zhuǎn)發(fā)的訂閱路徑”),去掉messagingTemplate,同時(shí)return msg來(lái)使用,return msg會(huì)去找@SendTo注解的路徑;
    2. 用法二:要么設(shè)置成void,使用messagingTemplate來(lái)控制轉(zhuǎn)發(fā)的訂閱路徑,且不能return msg

7. 添加websocket監(jiān)聽(tīng)事件

完成了上述代碼后,我們還需要對(duì)socket的連接和斷連事件進(jìn)行監(jiān)聽(tīng),這樣我們才能廣播用戶進(jìn)來(lái)和出去等操作。

@Component
public class WebSocketEventListener {

    private static final Logger logger = LoggerFactory.getLogger(WebSocketEventListener.class);

    @Autowired
    private SimpMessageSendingOperations messagingTemplate;

    @EventListener
    public void handleWebSocketConnectListener(SessionConnectedEvent event) {
        logger.info("Received a new web socket connection");
    }

    @EventListener
    public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
        StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());

        String username = (String) headerAccessor.getSessionAttributes().get("username");
        if(username != null) {
            logger.info("User Disconnected : " + username);

            ChatMessage chatMessage = new ChatMessage();
            chatMessage.setType(ChatMessage.MessageType.LEAVE);
            chatMessage.setSender(username);

            messagingTemplate.convertAndSend("/topic/public", chatMessage);
        }
    }
}

我們已經(jīng)在ChatController中定義的addUser()方法中廣播了用戶加入事件。因此,我們不需要在SessionConnected事件中執(zhí)行任何操作。

在SessionDisconnect事件中,編寫代碼用來(lái)從websocket會(huì)話中提取用戶名,并向所有連接的客戶端廣播用戶離開(kāi)事件。

8. 主要前端代碼:

'use strict';

var usernamePage = document.querySelector('#username-page');
var chatPage = document.querySelector('#chat-page');
var usernameForm = document.querySelector('#usernameForm');
var messageForm = document.querySelector('#messageForm');
var messageInput = document.querySelector('#message');
var messageArea = document.querySelector('#messageArea');
var connectingElement = document.querySelector('.connecting');

var stompClient = null;
var username = null;

var colors = [
    '#2196F3', '#32c787', '#00BCD4', '#ff5652',
    '#ffc107', '#ff85af', '#FF9800', '#39bbb0'
];

function connect(event) {
    username = document.querySelector('#name').value.trim();

    if(username) {
        usernamePage.classList.add('hidden');
        chatPage.classList.remove('hidden');

        var socket = new SockJS('/ws');
        stompClient = Stomp.over(socket);

        stompClient.connect({}, onConnected, onError);
    }
    event.preventDefault();
}


function onConnected() {
    // Subscribe to the Public Topic
    stompClient.subscribe('/topic/public', onMessageReceived);

    // Tell your username to the server
    stompClient.send("/app/chat.addUser",
        {},
        JSON.stringify({sender: username, type: 'JOIN'})
    )

    connectingElement.classList.add('hidden');
}


function onError(error) {
    connectingElement.textContent = 'Could not connect to WebSocket server. Please refresh this page to try again!';
    connectingElement.style.color = 'red';
}


function sendMessage(event) {
    var messageContent = messageInput.value.trim();

    if(messageContent && stompClient) {
        var chatMessage = {
            sender: username,
            content: messageInput.value,
            type: 'CHAT'
        };

        stompClient.send("/app/chat.sendMessage", {}, JSON.stringify(chatMessage));
        messageInput.value = '';
    }
    event.preventDefault();
}


function onMessageReceived(payload) {
    var message = JSON.parse(payload.body);

    var messageElement = document.createElement('li');

    if(message.type === 'JOIN') {
        messageElement.classList.add('event-message');
        message.content = message.sender + ' joined!';
    } else if (message.type === 'LEAVE') {
        messageElement.classList.add('event-message');
        message.content = message.sender + ' left!';
    } else {
        messageElement.classList.add('chat-message');

        var avatarElement = document.createElement('i');
        var avatarText = document.createTextNode(message.sender[0]);
        avatarElement.appendChild(avatarText);
        avatarElement.style['background-color'] = getAvatarColor(message.sender);

        messageElement.appendChild(avatarElement);

        var usernameElement = document.createElement('span');
        var usernameText = document.createTextNode(message.sender);
        usernameElement.appendChild(usernameText);
        messageElement.appendChild(usernameElement);
    }

    var textElement = document.createElement('p');
    var messageText = document.createTextNode(message.content);
    textElement.appendChild(messageText);

    messageElement.appendChild(textElement);

    messageArea.appendChild(messageElement);
    messageArea.scrollTop = messageArea.scrollHeight;
}


function getAvatarColor(messageSender) {
    var hash = 0;
    for (var i = 0; i < messageSender.length; i++) {
        hash = 31 * hash + messageSender.charCodeAt(i);
    }

    var index = Math.abs(hash % colors.length);
    return colors[index];
}

usernameForm.addEventListener('submit', connect, true)
messageForm.addEventListener('submit', sendMessage, true)

代碼解釋:

  • connect()函數(shù)使用SockJS和stomp客戶端連接到我們?cè)赟pring Boot中配置的/ws端點(diǎn)。
  • 成功連接后,客戶端訂閱/topic/public,并通過(guò)向/app/chat.addUser目的地發(fā)送消息將該用戶的名稱告知服務(wù)器。
  • stompClient.subscribe()函數(shù)采用一種回調(diào)方法,只要消息到達(dá)訂閱主題,就會(huì)調(diào)用該方法。
  • 其它的代碼用于在屏幕上顯示和格式化消息。

參考:
https://blog.csdn.net/xiangyangsanren/article/details/123970860
https://blog.csdn.net/qqxx6661/article/details/98883166
https://blog.csdn.net/qq_53021672/article/details/124313430
https://blog.csdn.net/qq_35387940/article/details/108276136(最全的)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-402719.html

到了這里,關(guān)于WebSocket(三) -- 使用websocket+stomp實(shí)現(xiàn)群聊功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • flutter開(kāi)發(fā)實(shí)戰(zhàn)-長(zhǎng)鏈接WebSocket使用stomp協(xié)議stomp_dart_client

    flutter開(kāi)發(fā)實(shí)戰(zhàn)-長(zhǎng)鏈接WebSocket使用stomp協(xié)議stomp_dart_client

    flutter開(kāi)發(fā)實(shí)戰(zhàn)-長(zhǎng)鏈接WebSocket使用stomp協(xié)議stomp_dart_client 在app中經(jīng)常會(huì)使用長(zhǎng)連接進(jìn)行消息通信,這里記錄一下基于websocket使用stomp協(xié)議的使用。 1.1 stomp介紹 stomp,Streaming Text Orientated Message Protocol,是流文本定向消息協(xié)議,是一種為MOM(Message Oriented Middleware,面向消息的中間件

    2024年02月13日
    瀏覽(26)
  • python的WebSocket編程詳解,案例群聊系統(tǒng)實(shí)現(xiàn)

    1.1為什么要用websocket 如果有需求要實(shí)現(xiàn)服務(wù)端向客戶端主動(dòng)推送消息時(shí)(比如聊天室,群聊室)有哪幾種方案 輪訓(xùn):讓瀏覽器每隔兩秒發(fā)送一次請(qǐng)求,缺點(diǎn):有延時(shí),請(qǐng)求太多網(wǎng)站壓力大; 長(zhǎng)輪訓(xùn):客戶端向服務(wù)端發(fā)送請(qǐng)求,服務(wù)端最多夯20秒,一旦有新的數(shù)據(jù)就立即返回

    2024年02月02日
    瀏覽(22)
  • 基于Springboot+WebSocket+Netty實(shí)現(xiàn)在線聊天、群聊系統(tǒng)

    基于Springboot+WebSocket+Netty實(shí)現(xiàn)在線聊天、群聊系統(tǒng)

    此文主要實(shí)現(xiàn)在好友添加、建群、聊天對(duì)話、群聊功能,使用Java作為后端語(yǔ)言進(jìn)行支持,界面友好,開(kāi)發(fā)簡(jiǎn)單。 2.1、下載安裝IntelliJ IDEA(后端語(yǔ)言開(kāi)發(fā)工具),Mysql數(shù)據(jù)庫(kù),微信Web開(kāi)發(fā)者工具。 1.創(chuàng)建maven project 先創(chuàng)建一個(gè)名為SpringBootDemo的項(xiàng)目,選擇【New Project】 然后在彈出

    2024年02月14日
    瀏覽(41)
  • Springboot 整合 WebSocket ,使用STOMP協(xié)議 ,前后端整合實(shí)戰(zhàn) (一)(1)

    Springboot 整合 WebSocket ,使用STOMP協(xié)議 ,前后端整合實(shí)戰(zhàn) (一)(1)

    server: port: 9908 3.WebSocketConfig.java import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springfra

    2024年04月25日
    瀏覽(25)
  • Springboot 整合 WebSocket ,使用STOMP協(xié)議+Redis 解決負(fù)載場(chǎng)景問(wèn)題

    Springboot 整合 WebSocket ,使用STOMP協(xié)議+Redis 解決負(fù)載場(chǎng)景問(wèn)題

    ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jacksonSeial.setObjectMapper(om); template.setValueSerializer(jacksonSeial); template.setKeySerializer(stringRedisSerializer); template.setHashKeySerializer(stringRedisSerializer); template

    2024年04月14日
    瀏覽(49)
  • SpringBoot與webSocket實(shí)現(xiàn)在線聊天室——實(shí)現(xiàn)私聊+群聊+聊天記錄保存

    SpringBoot與webSocket實(shí)現(xiàn)在線聊天室——實(shí)現(xiàn)私聊+群聊+聊天記錄保存

    引用參考:原文章地址:https://blog.csdn.net/qq_41463655/article/details/92410518 在此基礎(chǔ)上實(shí)現(xiàn)對(duì)聊天記錄的保存。 代碼地址:鏈接:https://pan.baidu.com/s/1IJFZDa4S_DF08773sKJWeA 提取碼:jkui 思路:新建一個(gè)實(shí)體類用于保存聊天記錄,在消息發(fā)送時(shí),設(shè)置對(duì)象的各個(gè)值然后保存到數(shù)據(jù)庫(kù)中。

    2024年02月02日
    瀏覽(88)
  • 使用 PHP WorkerMan 構(gòu)建 WebSocket 全雙工群聊通信(二)

    在很早很早以前,WebSocket 協(xié)議還沒(méi)有被發(fā)明的時(shí)候,人們?cè)?Web 端制作類實(shí)時(shí)數(shù)據(jù)動(dòng)態(tài)更新時(shí),一般采用輪詢、 長(zhǎng)連接 (Long Polling) 來(lái)實(shí)現(xiàn)。大概就是: 輪詢:客戶端不停發(fā)送 HTTP 請(qǐng)求給服務(wù)端,服務(wù)端返回最新數(shù)據(jù) 長(zhǎng)連接:客戶端發(fā)送一條 HTTP 請(qǐng)求給服務(wù)端,服務(wù)端 HOLD

    2024年02月09日
    瀏覽(22)
  • 使用WebSocket方式能將群聊信息實(shí)時(shí)群發(fā)給所有在線用戶

    1.1 什么是WebSocket WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的網(wǎng)絡(luò)協(xié)議。它是為了在Web瀏覽器和Web服務(wù)器之間提供實(shí)時(shí)、雙向的通信而設(shè)計(jì)的。傳統(tǒng)的HTTP協(xié)議是一種單向通信協(xié)議,客戶端發(fā)送請(qǐng)求,服務(wù)器響應(yīng),然后連接就關(guān)閉了。而WebSocket允許在客戶端和服務(wù)器之間建

    2024年02月03日
    瀏覽(17)
  • Spring Boot 3 + Vue 3 整合 WebSocket (STOMP協(xié)議) 實(shí)現(xiàn)廣播和點(diǎn)對(duì)點(diǎn)實(shí)時(shí)消息

    Spring Boot 3 + Vue 3 整合 WebSocket (STOMP協(xié)議) 實(shí)現(xiàn)廣播和點(diǎn)對(duì)點(diǎn)實(shí)時(shí)消息

    ?? 作者主頁(yè): 有來(lái)技術(shù) ?? 開(kāi)源項(xiàng)目: youlai-mall ?? vue3-element-admin ?? youlai-boot ?? 倉(cāng)庫(kù)主頁(yè): Gitee ?? Github ?? GitCode ?? 歡迎點(diǎn)贊 ?? 收藏 ?留言 ?? 如有錯(cuò)誤敬請(qǐng)糾正! WebSocket是一種在Web瀏覽器與Web服務(wù)器之間建立雙向通信的協(xié)議,而Spring Boot提供了便捷的WebSocket支持

    2024年02月02日
    瀏覽(17)
  • 使用WebSocket實(shí)現(xiàn)聊天功能

    使用WebSocket實(shí)現(xiàn)一對(duì)一的聊天功能與未讀消息功能 會(huì)話表 字段名 字段類型 長(zhǎng)度 注釋 conversation_id int 11 會(huì)話ID create_time datetime 創(chuàng)建時(shí)間 conversation_type int 1 會(huì)話類型 消息表 字段名 字段類型 長(zhǎng)度 注釋 message_id int 11 消息ID conversation_id int 11 會(huì)話ID sender_id int 11 發(fā)送者ID receiver

    2024年02月11日
    瀏覽(19)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包