• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

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

24.05.20 01:44 작성 조회수 88

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 

답변 1

답변을 작성해보세요.

1

July님의 프로필

July

지식공유자

2024.05.20

안녕하세요 👋

 

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

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

 

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

 

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

 

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

 

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

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

김동주님의 프로필

김동주

질문자

2024.06.02

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

채널톡 아이콘