inflearn logo
강의

講義

知識共有

大容量チャットTPS処理のためのWebSocket通信を作りながら学ぶ

socket message イベント処理のための client 関数の作成

채팅이 2번씩 전송되는 현상 질문

解決済みの質問

314

harhyom91896752

投稿した質問数 1

1

안녕하세요 go 서버 구축 이후 프론트 연결하여 채팅을 전송하면 같은 메시지가 두 번씩 전송되는 현상이 발생합니다.

강의를 여러 번 체크하면서 봤는데 소스 코드가 다른 점은 찾지 못했습니다.

 

제가 작성한 socket.go 코드인데 어떤 부분이 문제가 있을까요

package network

import (
	"chat_server_golang/types"
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
) 


var upgrader = &websocket.Upgrader{ReadBufferSize: types.SocketBufferSize, WriteBufferSize: types.MessageBufferSize,
	CheckOrigin: func(r *http.Request) bool {return true},
	} // http 요청을 websocket 통신으로 업그레이드 해준다.


type message struct {
	Name string
	Message string
	Time int64
}

type Room struct {
	Forward chan *message
	Join chan *client
	Leave chan *client

	Clients map[*client]bool
}

type client struct {
	Send chan *message
	Room *Room
	Name string
	Socket *websocket.Conn
}

func NewRoom() *Room {
	return &Room {
		Forward: make(chan *message),
		Join: make(chan *client),
		Leave: make(chan *client),
		Clients: make(map[*client]bool),
	}
}

func (c *client) Read() {
	// 클라이언트가 들어오는 멧세지를 읽는 작업
	defer c.Socket.Close()
	for {
		var msg message
		err := c.Socket.ReadJSON(&msg)
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
				break
			}
			panic(err)
		} else {
			log.Println("READ : ", msg, "client", c.Name)
			log.Println()

			msg.Time = time.Now().Unix()
			msg.Name = c.Name

			c.Room.Forward <- &msg
		}

		msg.Name = c.Name
		c.Room.Forward <- &msg
	}
}

func (c *client) Write() {
	// 클라이언트가 나가는 메시지를 전송하는 작업
	defer c.Socket.Close()

	for msg := range c.Send {
		log.Println("WRITE : ", msg, "client", c.Name)
		log.Println()

		err := c.Socket.WriteJSON(msg)
		if err != nil {
			panic(err)
		}	
	}
}


func (r *Room) RunInit() {
	// room 에 있는 모든 채널 값을 받는 작업
	// join leave 등의 메시지 큐를 처리, 무한반복문을 돌면서 처리
	for {
		log.Println(r.Clients)
		log.Println(r.Forward)
		select {
		case client := <-r.Join:
			r.Clients[client] = true
		case client := <-r.Leave:
			r.Clients[client] = false

			close(client.Send)

			delete(r.Clients, client)
		case msg := <-r.Forward:
			for client := range r.Clients {
				client.Send <- msg
			}
		}
	}
}

func (r *Room) SocketServe(c *gin.Context) {
	socket, err := upgrader.Upgrade(c.Writer, c.Request, nil)

	if err != nil {
		panic(err)
	}

	userCookie, err := c.Request.Cookie("auth")
	
	if err != nil {
		panic(err)
	}

	log.Println("userCookie", userCookie)

	client := &client{
		Socket: socket,
		Send: make(chan *message, types.MessageBufferSize),
		Room: r,
		Name: userCookie.Value,
	}

	r.Join <- client // 채팅방에 클라이언트가 들어왔다고 알림	

	defer func() { r.Leave <- client }() // 클라이언트가 나갔다고 알림, 클라이언트가 나가면서 defer 함수가 실행된다.

	go client.Write()
	client.Read()
}
2024/05/20 01:39:17 userCookie auth=one
2024/05/20 01:39:17 map[0x14000512600:true]
2024/05/20 01:39:17 0x14000192600
2024/05/20 01:39:21 READ :  { hi 0} client one
2024/05/20 01:39:21 
2024/05/20 01:39:21 map[0x14000512600:true]
2024/05/20 01:39:21 0x14000192600
2024/05/20 01:39:21 map[0x14000512600:true]
2024/05/20 01:39:21 0x14000192600
2024/05/20 01:39:21 WRITE :  &{one hi 1716136761} client one
2024/05/20 01:39:21 
2024/05/20 01:39:21 WRITE :  &{one hi 1716136761} client one
2024/05/20 01:39:21 

go websockets

回答 1

1

July

안녕하세요 👋

 

메시지가 두개씩 나오는 이유로 질문을 주셨습니다.

소스를 확인해보니 의심할 부분이 보이는거 같아요.

 

Read함수를 보시면 Forward에 두번 전송을 하고 있습니다.

 

그러면 채널이 두개의 값을 전달받아 처리가 될 우려가 있어요!! 🤔🤔

 

그러니 한번의 전송만 진행하게 코드를 수정해보시면 어떨까싶네요.🎉

 

한번 진행해보시고 해결이 안된다면 다시 질문 부탁드립니다.

늦은시간까지 열심히 하시네요!! 화이팅👏

1

harhyom91896752

한 곳의 msg forward를 제거하니 정상적으로 동작했습니다. 감사합니다.

gRPC 실무에서 질문

0

35

2

교안에 사용되는 app.js 파일은 어디서 받을수 있을까요?

0

42

1

소스 download

0

43

2

프로젝트 구조 관련 질문이 있습니다.

0

47

1

커넥션 min, max 설정과 관련하여

0

50

1

명령어 오류가 있으신 분들 저는 이렇게 해결했어요!

0

70

1

Streaming 중인 서비스에서 모든 파드에 broadcast하는 방법

0

118

3

프론트쪽이 리액트로 되어있는데요..

0

123

2

오늘 강의 듣기 시작했는데요!

0

132

2

RunInit() 관련 질문

0

180

5

소켓 연결과 http

0

154

2

학습자료는 어디서 받나요?

1

200

1

현재 강의에서 재생관련 문제가 있어서 전달드립니다.

1

202

2

강의에 음성만 나오고 영상이 나오질 않습니다 ㅠ

0

142

1

데이터 불러오기

1

143

1

panic 사용

1

116

1

defer 사용

1

129

1

nodejs 파일이 프론트엔디 파일인가요??

0

221

1

채팅 메시지 DB로 저장 하기.

1

843

2

뭔가 중간에 오타를 쳤는지 오류가 자꾸 발생하는데 혹시 go 소스코드 볼수있는곳 있나요?

1

247

1

다른 질문을 읽고 궁금한 점이 생겼습니다.

1

303

1

소켓 서버의 수평적 확장 및 무중단 배포에 대해 질문드립니다!

3

1306

2

app.js를 여러 번 실행했음에도 불구하고, 로그가 단 한 번만 출력됨

1

336

2

몇천명이 Room 에 동시접속할 수 있도록 설계하려면 어떤 것들이 필요할까요?

1

473

2