Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Archives
Today
Total
관리 메뉴

빵공장

Websocket을 이용하여 간단한 채팅 만들어 보기 본문

Golang

Websocket을 이용하여 간단한 채팅 만들어 보기

sucream 2020. 9. 9. 02:52

1. 서버 코드

코드는 기본적으로 github.com/labstack/echo를 이용하였으며, 추가로 웹소켓을 위해 github.com/gorilla/websocket를 이용하였다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package main
 
import (
    "log"
 
    "github.com/gorilla/websocket"
    "github.com/labstack/echo"
    "github.com/labstack/echo/middleware"
)
 
var (
    upgrader  = websocket.Upgrader{}
    clients   = make(map[*websocket.Conn]bool)
    broadcast = make(chan Message)
)
 
type Message struct {
    Username string `json:"username"`
    Message  string `json:"message"`
    Event    string `json:"event"`
}
 
func handleMessages() {
    for {
        msg := <-broadcast
        switch msg.Event {
        case "OPEN":
            for client := range clients {
                err := client.WriteJSON(msg)
                if err != nil {
                    log.Printf("error: %v", err)
                    client.Close()
                    delete(clients, client)
                }
            }
        case "MESSAGE":
            for client := range clients {
                err := client.WriteJSON(msg)
                if err != nil {
                    log.Printf("error: %v", err)
                    client.Close()
                    delete(clients, client)
                }
            }
        }
    }
}
 
func hello(c echo.Context) error {
    ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
    if err != nil {
        return err
    }
    defer ws.Close()
 
    clients[ws] = true
 
    for {
 
        var msg Message
        err := ws.ReadJSON(&msg)
 
        if err != nil {
            log.Printf("error: %v", err)
            delete(clients, ws)
            break
        }
        broadcast <- msg
    }
    return nil
}
 
func main() {
    e := echo.New()
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())
    e.Static("/""./templates")
    e.GET("/ws", hello)
    go handleMessages()
    e.Logger.Fatal(e.Start(":8888"))
}
 
cs

2. 클라이언트 코드

클라이언트도 크게 복잡하지 않다.

websocket을 이용하여 상황에 따라 새로운 사용자 알림 및 메시지를 적절히 출력하도록 하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<!DOCTYPE html>
<html>
<head>
    <title>ws</title>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <style>
        * {
            text-align: center;
        }
        #chat {
            font-size: large;
            text-align: left;
        }
    </style>
</head>
<body>
    <div>
        <h1>가가-가가 라이브</h1>
        <textarea rows="20" cols="50" id="chat" readonly="readonly"></textarea><br>
        <input type="text" id="username" value="" size="10" placeholder="닉네임 입력">
        <input type="text" id="message" size="30" placeholder="내용"><input type="button" value="전송" onclick="myOnClick()">
    </div>
</body>
<script>
    var ws = new WebSocket('ws://localhost:8888/ws');
 
    ws.onopen = (event=> {
        $('#username').val()
        let sendData = {event"OPEN"}
        ws.send(JSON.stringify(sendData));
    }
 
    ws.onmessage = (event=> {
        console.log(event.data);
        let recData = JSON.parse(event.data);
        let now = new Date();
        const top = $('#chat').prop('scrollHeight');
        console.log(recData.event);
        switch (recData.event) {
            case "OPEN":
                $('#chat').val($('#chat').val()+"["+now.getHours()+"시"+now.getMinutes() + "분] --- 새로운 사용자가 접속했습니다. ---\n");
                $('#chat').scrollTop(top);
                notify("새로운 사용자 접속")
                break;
            case "MESSAGE":
                $('#chat').val($('#chat').val()+"["+now.getHours()+"시"+now.getMinutes() + "분] " + recData.username + ": " + recData.message + '\n');
                $('#chat').scrollTop(top);
                notify("새로운 메시지 도착")
                break;
            default:
                break;
        }
        
    }
 
    $("#message").keydown(function(key) {
                if (key.keyCode == 13) {
                    myOnClick();
                }
            });
 
    function myOnClick() {
        if ($('#username').val() != "" && $('#message').val() != "") {
            let sendData = {username:$('#username').val(), message: $('#message').val(), event:"MESSAGE"};
            ws.send(JSON.stringify(sendData));
            $('#message').val('');
        }
    }
</script>
</html>
 
cs

추가로 채팅이 올때 웹브라우저에서 알림을 보내주는 기능(HTML 표준에 있는것 같음)을 이용하려 했는데 ssl 인증서 받고 추가 작업을 해야 해서 나중에 하기로 함...

'Golang' 카테고리의 다른 글

한글 자모 분리기 만들어 보기  (0) 2020.09.09
Comments