[도해] 채팅방과 사용자의 모델링 [O'Reilley/Golang/웹 응용]

개요
Go 언어로 웹 응용 프로그램 개발(O'Reilley)의 Chapter 1.모형도를 써서 2.4의 내용을 개괄하다
디자인을 하고 코드를 쓰거나 읽으면 이해하기 쉬우니까 참고로
모델링
사용자

client.go
type client struct {
    socket *websocket.Conn
    send chan []byte
    room *room
}
채팅방

소스 코드
room.go
type room struct {
    forward chan []byte
    join chan *client
    leave chan *client
    clients map[*client]bool
}
우편물을 수발하다.

애당초read () 및 clientwrite () 가 서버 측면에서 읽기와 쓰기를 본 것인지 모르겠습니다.
소스 코드
client.go
func (c *client) read() {
    for {
        if _, msg, err := c.socket.ReadMessage(); err == nil {
            c.room.forward <- msg
        } else {
            break
        }
    }
    c.socket.Close()
}

func (c *client) write() {
    for msg := range c.send {
        if err := c.socket.WriteMessage(websocket.TextMessage, msg); err != nil {
            break
        }
    }
    c.socket.Close()
}
room.go
func (r *room) run() {
    for {
        select {
        // caseが同時に実行されることはない
        case client := <-r.join:
            // 参加
            r.clients[client] = true
        case client := <-r.leave:
            // 退室
            delete(r.clients, client)
            close(client.send)
        case msg := <-r.forward:
            // すべてのクライアントにメッセージを転送
            for client := range r.clients {
                select {
                // メッセージを送信
                case client.send <- msg:
                default:
                    // 送信に失敗
                    delete(r.clients, client)
                    close(client.send)
                }
            }
        }
    }
}
사용자와의 연결 설정
참고로 발송과 수신 모드에서 설명하지 않은 첫 번째 사용자가 채팅방에 들어갈 때의 절차를 총결하였다.
  • HTTP 연결을 업그레이드하여 Websocket
  • 사용
  • 사용자가 채팅방에 들어오는 HTTP 요청을 건너뛰기
  • room.ServeHTTP 메서드 호출
  • upgrader.Upgrade 방법WebSocket 연결 획득
  • 연결이 성공하면client,room을 생성합니다.join 채널로 전달
  • 지연 처리
  • 로 클라이언트 종료 시 종료
  • 병렬 처리 중 메시지 수신 대기
  • 주 라인에서 메시지 발송 대기
  • 소스 코드
    room.go
    const (
        socketBufferSize = 1024
        messageBuffuerSize = 256
    )
    
    // HTTP接続をアップグレードしてWebSocketを使えるようにする
    var upgrader = &websocket.Upgrader{ReadBufferSize: socketBufferSize,WriteBufferSize: socketBufferSize}
    
    func (r *room) ServeHTTP(w http.ResponseWriter, req *http.Request)  {
        // WebSocketコネクションを取得
        socket, err := upgrader.Upgrade(w,req,nil)
        if err != nil {
            log.Fatal("ServeHTTP:", err)
            return
        }
        client := &client{
            socket: socket,
            send: make(chan []byte,messageBuffuerSize),
            room: r,
        }
        r.join <- client
        defer func() {r.leave <- client}()
        go client.write()
        client.read()
    }
    
    참고 자료
    Go 언어로 웹 응용 프로그램 개발(O'Reilley)

    좋은 웹페이지 즐겨찾기