강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của harhyom91896752
harhyom91896752

câu hỏi đã được viết

Học cách xây dựng giao tiếp WebSocket để xử lý TPS chat lớn

Viết hàm máy khách để xử lý các sự kiện thông báo ổ cắm

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

Đã giải quyết

Viết

·

307

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 

gowebsockets

Câu trả lời 1

1

July님의 프로필 이미지
July
Người chia sẻ kiến thức

안녕하세요 👋

 

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

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

 

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

 

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

 

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

 

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

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

harhyom91896752님의 프로필 이미지
harhyom91896752
Người đặt câu hỏi

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

Hình ảnh hồ sơ của harhyom91896752
harhyom91896752

câu hỏi đã được viết

Đặt câu hỏi